在 Stomp Disconnect 命令上拒绝 Spring WebSocket 访问

Posted

技术标签:

【中文标题】在 Stomp Disconnect 命令上拒绝 Spring WebSocket 访问【英文标题】:Spring WebSocket Access Denied on Stomp Disconnect Command 【发布时间】:2021-08-18 17:28:07 【问题描述】:

我遇到的一个问题需要您的帮助。我正在使用 Spring WebSocket |弹簧安全。

发生了什么

Stomp 客户端能够成功连接,但一段时间后我收到此异常

2021-05-31 11:35:24.563  INFO 1 --- [nio-8080-exec-4] o.s.w.s.m.SubProtocolWebSocketHandler    : No messages received after 114650 ms. Closing htmlFileStreamingSockJsSession[id=hkui12fj].
Error Occured on stomp Command : DISCONNECT
2021-05-31 11:35:24.563 ERROR 1 --- [nio-8080-exec-4] c.s.c.w.e.ConnectDisconnectEventHandler  : Error Occured in the system null
2021-05-31 11:35:24.564  WARN 1 --- [nio-8080-exec-4] w.s.h.ExceptionWebSocketHandlerDecorator : Unhandled exception after connection closed for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=SubProtocolWebSocketHandler[StompSubProtocolHandler[v10.stomp, v11.stomp, v12.stomp]]]]

org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:149) ~[spring-messaging-5.3.5.jar!/:5.3.5]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:125) ~[spring-messaging-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.messaging.StompSubProtocolHandler.afterSessionEnded(StompSubProtocolHandler.java:650) ~[spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.clearSession(SubProtocolWebSocketHandler.java:530) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.afterConnectionClosed(SubProtocolWebSocketHandler.java:399) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.close(AbstractSockJsSession.java:224) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.WebSocketSessionDecorator.close(WebSocketSessionDecorator.java:160) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.close(ConcurrentWebSocketSessionDecorator.java:271) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.checkSessions(SubProtocolWebSocketHandler.java:507) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:339) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.delegateMessages(AbstractSockJsSession.java:387) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.handleMessage(WebSocketServerSockJsSession.java:195) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler.handleTextMessage(SockJsWebSocketHandler.java:93) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:114) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:43) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:85) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:82) [spring-websocket-5.3.5.jar!/:5.3.5]
    at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:415) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:129) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:515) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:301) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:85) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:183) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:162) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:156) [tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:60) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_212]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_212]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.4.5.jar!/:5.4.5]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238) ~[spring-security-core-5.4.5.jar!/:5.4.5]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208) ~[spring-security-core-5.4.5.jar!/:5.4.5]
    at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:70) ~[spring-security-messaging-5.4.5.jar!/:5.4.5]
    at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:181) ~[spring-messaging-5.3.5.jar!/:5.3.5]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:135) ~[spring-messaging-5.3.5.jar!/:5.3.5]
    ... 41 common frames omitted

我发现它发生在 Stomp Disconnect Command 上。

WebSocket 安全配置只需几件事。

@Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) 
        messages.anyMessage().authenticated();
    

    @Override
    protected boolean sameOriginDisabled() 
        return true;
    

任何帮助将不胜感激。

我有两个以这种方式注册的拦截器。

首先WebSocketAuthenticationFilter它只是一个通道拦截器,用于拦截传入的请求并将用户设置为在websocket中经过身份验证。

第二个 - ConnectDisconnectChannelInterceptor 我跟踪用户何时连接和断开连接。

【问题讨论】:

【参考方案1】:
 @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messageSecurityMetadataSourceRegistry) 
        messageSecurityMetadataSourceRegistry
                .simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT, SimpMessageType.OTHER).permitAll()
                .anyMessage().authenticated();
    

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于在 Stomp Disconnect 命令上拒绝 Spring WebSocket 访问的主要内容,如果未能解决你的问题,请参考以下文章

Blazor 应用程序 /_blazor/disconnect 状态码 400

在 sock.js 上使用 stomp.js 和 ActiveMQ-Apollo 似乎不起作用

ActiveMQ 无法识别 Stomp:传输方案无法识别:[stomp+ssl]

如何将事务与 Stomp 和 ActiveMQ(和 Perl)一起使用?

启用 stomp 后的 activemq oom

Server Disconnect