I'm using Spring 4.3.5 and WebSocket with SockJS, STOMP and SimpleBrokerMessageHandler.
In my application I have three separate WebSocket endpoints running on a different address: /endPointA, /ednpointB, /endpointC To be even more specific, I have three separate configuration classes annotated with @Configuration @EnableWebSocketMessageBroker annotations.
I also have a Class that has @Autowired SimpMessagingTemplate.
Finally I have three clients, each connected to one, different EndPoint. All of them, however are subscribed to the "same" channel address which is /topic/messages
When I use SimpMessagingTemplate to send something to /topic/messages, then all clients receives this message.
After that I have two questions:
I did some investigation (heap dump analysis) and I found that for my configuration I have:
So I wonder, if this message propagation over all endpoits is a "feature" of SimpleBrokerMessageHandler or SimpMessagingTemplate.
I facing the same issue in a multi-tenant application that I solved thanks to this thread :
My websocket endpoint is: ws://127.0.0.1/my-context-app/ws
, java config file is:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*");
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
}
My websocket queues url forms are prefixed by tenant-id: /[tenant-id]/[url-of-queue].
Each client subscribe on its own tenant-id. It can not subscribe to queue of another client thanks to WebSocketSecurityConfig.configureInbound(MessageSecurityMetadataSourceRegistry) method and a custom spring bean which has a 'websocket-queue-subscription-security-check' method :
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpSubscribeDestMatchers("/**")
.access("@customWSSecurityCheck.isSubscriptionAllowed(authentication, message)");
}
}
My custom bean named customWSSecurityCheck check if authenticated user is allowed to subscribe on queue. Keep in mind that CustomAuthentication implements org.springframework.security.core.Authentication with additional tenantId attribute that is filled by additional code not mentioned there on a custom spring security filter / authentication method:
@Bean()
public class CustomWSSecurityCheck {
public boolean isSubscriptionAllowed(CustomAuthentication authentication, Message message) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
String url = sha.getDestination().substring(1);
String tenantId = url.substring(0, url.indexOf("/"));
return tenantId.equals(authentication.getTenantId());
}
}
Of course It involve that every message sended by the server should be prefixed by the right tenant-id: MessagingService.convertAndSend("[tenant-id]/[url-of-queue]", messagePayload)