【问题标题】:How to intercept connection and subscription with Spring Stomp如何使用 Spring Stomp 拦截连接和订阅
【发布时间】:2018-09-20 06:05:06
【问题描述】:

我需要在我的 websocket spring 服务器中控制 stomp 客户端的连接/断开和订阅/取消订阅。 这是主要的配置类:

@Configuration
@ComponentScan(basePackages = "com.test")
@EnableWebSocketMessageBroker
@EnableWebMvc
public class Config extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue", "/topic");
        config.setApplicationDestinationPrefixes("/app");
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/stomp").setAllowedOrigins("*").addInterceptors(getInterceptot());
    }

    private HandshakeInterceptor getInterceptot() {
        return new HandshakeInterceptor(){

            @Override
            public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
                return true; //TODO
            }

            @Override
            public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {}

        };
    }

}

我可以用beforeHandshake方法拦截连接事件,但我不知道这是否是最好的方法。

此外,我需要检查所有断开连接、订阅和取消订阅,我尝试使用 @SubscribeMapping("/**") 注释,但它对我不起作用。

我试过了:

@Component
public class StompEventListener {

    @EventListener
    private void handleSessionConnected(SessionConnectEvent event) {

    }

    @EventListener
    private void handleSessionDisconnect(SessionDisconnectEvent event) {

    }

    @EventListener
    private void handleSessionSubscribeEvent(SessionSubscribeEvent event) {

    }

    @EventListener
    private void handleSessionUnsubscribeEvent(SessionUnsubscribeEvent event) {

    }
}

它可以工作,但我需要拦截这个请求,我应该拒绝/授予所有操作,例如我可以决定拒绝连接,但使用 @EventListener 我不能这样做,因为它是在连接之后调用的。

【问题讨论】:

    标签: websocket stomp spring-websocket


    【解决方案1】:

    使用HandshakeInterceptor,您将无法获得 CONNECT / DISCONNECT 帧。您必须实现ChannelInterceptor(或扩展ChannelInterceptorAdapter)并将其添加到clientInboundChannelpreSend 方法允许您在处理消息之前添加逻辑:

    public class FilterChannelInterceptor extends ChannelInterceptorAdapter {
        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
            if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand()) {
                // Your logic
            }
            return message;
        }
    }
    

    查看 Spring Security 拦截器,这可能是一个很好的起点:https://github.com/spring-projects/spring-security/blob/master/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java

    【讨论】:

    • 谢谢,我可以从 preSend 的 MessageChannel 参数中获取客户端 IP 地址吗?
    • 您可以实现一个HandshakeInterceptor,它在握手期间获取 IP 并将其公开给 WebSocket 会话。我已经在这里回答了:stackoverflow.com/questions/31669927/…
    猜你喜欢
    • 2017-07-24
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 2018-10-31
    • 2016-11-09
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多