如何使用 Spring Stomp 拦截连接和订阅
How to intercept connection and subscription with Spring Stomp
我需要在我的 websocket spring 服务器中控制 connection/disconnection 和 subscriptions/unsubscriptions 的 stomp 客户端。
这是主要配置 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) {}
};
}
}
我可以用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) {
}
}
它有效,但我需要拦截这个请求,我应该 deny/grant 所有操作,例如我可以决定拒绝连接但是 @EventListener
我不能这样做,因为它被称为连接后。
使用 HandshakeInterceptor
您将无法获得 CONNECT / DISCONNECT 帧。您必须实现 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 安全拦截器,这可能是一个很好的起点:https://github.com/spring-projects/spring-security/blob/master/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java
我需要在我的 websocket spring 服务器中控制 connection/disconnection 和 subscriptions/unsubscriptions 的 stomp 客户端。 这是主要配置 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) {}
};
}
}
我可以用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) {
}
}
它有效,但我需要拦截这个请求,我应该 deny/grant 所有操作,例如我可以决定拒绝连接但是 @EventListener
我不能这样做,因为它被称为连接后。
使用 HandshakeInterceptor
您将无法获得 CONNECT / DISCONNECT 帧。您必须实现 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 安全拦截器,这可能是一个很好的起点:https://github.com/spring-projects/spring-security/blob/master/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java