我正在使用 Spring 的 STOMP over WebSocket 实现和功能齐全的 ActiveMQ 代理。当用户SUBSCRIBE
对于一个主题,有一些权限逻辑,必须经过一些权限逻辑,才能成功订阅。我正在使用 ChannelInterceptor 来应用权限逻辑,配置如下:
WebSocketConfig.java:
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost("relayhost.mydomain.com")
.setRelayPort(61613);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new MySubscriptionInterceptor());
}
}
WebSocketSecurityConfig.java:
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpSubscribeDestMatchers("/stomp/**").authenticated()
.simpSubscribeDestMatchers("/user/queue/errors").authenticated()
.anyMessage().denyAll();
}
}
MySubscriptionInterceptor.java:
public class MySubscriptionInterceptor extends ChannelInterceptorAdapter {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
Principal principal = headerAccessor.getUser();
if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
checkPermissions(principal);
}
return message;
}
private void checkPermissions(Principal principal) {
// apply permissions logic
// throw Exception permissions not sufficient
}
}
当没有足够权限的客户端尝试订阅受限主题时,他们实际上从未收到来自该主题的任何消息,但也不会收到拒绝其订阅的抛出异常的通知。相反,客户端会收到一个 ActiveMQ 代理一无所知的死订阅。 (正常的、获得充分许可的客户端与 STOMP 端点和主题的交互按预期工作。)
我尝试过订阅users/{subscribingUsername}/queue/errors
简单地说users/queue/errors
成功连接后与我的 Java 测试客户端一起使用,但到目前为止我无法从服务器传递到客户端获取有关订阅异常的错误消息。这显然不太理想,因为客户永远不会收到他们被拒绝访问的通知。