我正在使用Spring 4.3.5和WebSocket与SockJS,STOMP和SimpleBrokerMessageHandler。
在我的应用程序中,我有三个独立的WebSocket端点在不同的地址上运行: / endPointA,/ ednpointB,/ endpointC 更具体地说,我有三个单独的配置类,用@Configuration @EnableWebSocketMessageBroker注释注释。
我还有一个拥有@Autowired SimpMessagingTemplate的类。
最后我有三个客户端,每个客户端连接到一个不同的EndPoint。 但是,所有这些都订阅了“相同”的频道地址,即 / topic / messages
当我使用 SimpMessagingTemplate 向 / topic / messages 发送内容时,所有客户端都会收到此消息。
之后我有两个问题:
我做了一些调查(堆转储分析),我发现对于我的配置我有:
所以我想知道,如果这个消息在所有endpoits上的传播是SimpleBrokerMessageHandler或SimpMessagingTemplate的“特性”。
答案 0 :(得分:2)
在this thread的帮助下,我在多租户应用程序中遇到了相同的问题:
我的websocket端点是:ws://127.0.0.1/my-context-app/ws
,java配置文件为:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*");
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
}
我的websocket队列url形式以tenant-id为前缀:/[tenant-id]/[url-of-queue]
。
每个客户端都订阅自己的租户ID。由于WebSocketSecurityConfig.configureInbound(MessageSecurityMetadataSourceRegistry)
方法和具有'websocket-queue-subscription-security-check'方法的自定义spring bean,它无法预订另一个客户端的队列:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpSubscribeDestMatchers("/**")
.access("@customWSSecurityCheck.isSubscriptionAllowed(authentication, message)");
}
}
我的名为customWSSecurityCheck的自定义bean检查是否允许经过身份验证的用户在队列上进行订阅。请记住,CustomAuthentication
用附加的tenantId属性实现org.springframework.security.core.Authentication
,该属性由在自定义spring安全过滤器/身份验证方法上未提及的其他代码填充:
@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());
}
}
当然,这涉及到服务器发送的每条消息均应带有正确的租户ID:MessagingService.convertAndSend("[tenant-id]/[url-of-queue]", messagePayload)