代码之家  ›  专栏  ›  技术社区  ›  Tobia

如何使用Spring Stomp拦截连接和订阅

  •  7
  • Tobia  · 技术社区  · 6 年前

    我需要控制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 我无法执行此操作,因为它是在连接后调用的。

    1 回复  |  直到 6 年前
        1
  •  6
  •   Sergi Almar    6 年前

    使用 HandshakeInterceptor 您将无法获取连接/断开帧。您必须实现 ChannelInterceptor (或扩展ChannelInterceptorAdapter)并将其添加到 clientInboundChannel 这个 preSend 方法允许您在处理消息之前添加逻辑:

    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