Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to intercept connection and subscription with Spring Stomp

I need to control connection/disconnection and subscriptions/unsubscriptions of stomp clients in my websocket spring server. This is the main configuration class:

@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) {}

        };
    }

}

I could intercept the connection event with beforeHandshake method, but I don't know if this is the best way.

Moreover I need to check all disconnections, subscription and unsubscriptions, I tried to use @SubscribeMapping("/**") annotation but it doesn't work for me.

I tried this:

@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) {

    }
}

It works, but I need to intercept this request and I should deny/grant all operations, for example I can decide to deny the connection but with @EventListener I cannot do this because it is called after the connection.

like image 896
Tobia Avatar asked Apr 10 '18 14:04

Tobia


People also ask

What is STOMP broker relay?

STOMP is a simple text-oriented messaging protocol that was originally created for scripting languages such as Ruby, Python, and Perl to connect to enterprise message brokers. It is designed to address a subset of commonly used messaging patterns.

Does Spring boot support WebSocket?

Spring Boot includes the spring-WebSocket module, which is compatible with the Java WebSocket API standard (JSR-356). Implementing the WebSocket server-side with Spring Boot is not a very complex task and includes only a couple of steps, which we will walk through one by one.


1 Answers

With a HandshakeInterceptor you won't be able to get CONNECT / DISCONNECT frames. You have to implement a ChannelInterceptor (or extend ChannelInterceptorAdapter) and add it to the clientInboundChannel. The preSend method allows you to add your logic before the message is processed:

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;
    }
}

Check out the Spring Security interceptor, which might be a good starting point: https://github.com/spring-projects/spring-security/blob/master/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java

like image 85
Sergi Almar Avatar answered Sep 26 '22 06:09

Sergi Almar