【发布时间】:2018-07-19 05:14:38
【问题描述】:
问题
有没有办法全局处理 Spring WebSocket 模块中的错误(通常权限不足)导致的 Spring Messaging MessageDeliveryException?
用例
我已经通过 STOMP 实现了 Spring WebSockets 以支持我的 web 应用程序中的 ws 连接。为了保护 websocket 端点,我创建了拦截器,授权用户在 STOMP CONNECT 时间启动 STOMP 会话(如 Spring 文档 here in 22.4.11 section 中所建议):
@Component
public class StompMessagingInterceptor extends ChannelInterceptorAdapter {
// Some code not important to the problem
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
switch (headerAccessor.getCommand()) {
// Authenticate STOMP session on CONNECT using jwt token passed as a STOMP login header - it's working great
case CONNECT:
authorizeStompSession(headerAccessor);
break;
}
// Returns processed message
return message;
}
// Another part of code not important for the problem
}
并包含 spring-security-messaging 配置以在消息传递时添加对权限的一些细粒度控制:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpTypeMatchers(
SimpMessageType.CONNECT,
SimpMessageType.DISCONNECT,
SimpMessageType.HEARTBEAT
).authenticated()
.simpSubscribeDestMatchers("/queue/general").authenticated()
.simpSubscribeDestMatchers("/user/queue/priv").authenticated()
.simpDestMatchers("/app/general").authenticated()
.simpDestMatchers("/user/*/queue/priv").hasAuthority("ADMIN")
.anyMessage().denyAll();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
首先 - 此配置按预期工作,问题是在 websocket 通信期间发生一些安全异常(例如没有管理员权限的用户尝试在“/user/{something}/queue/priv”端点上发送消息)它将在 org.springframework.messaging.MessageDeliveryException 上升结束并且:
- 完整的异常堆栈跟踪记录到我的服务器日志中
- 返回包含部分堆栈跟踪的 STOMP ERROR 帧,因为它是
message字段。
我想要做的是捕获(如果可能的话在全球范围内)DeliveryException,检查导致它的原因并相应地创建我自己的消息以在 STOMP ERROR 框架中返回(假设使用一些错误代码,例如 403 来模仿HTTP),而不是进一步抛出原始异常,只是用我的记录器记录一些警告。有可能吗?
我尝试了什么
在寻找解决方案时,我发现有些人使用@MessageExceptionHandler 来捕获消息异常,Spring 4.2.3(我使用的版本)文档只提到了一次here in 25.4.11 section。我试着这样使用它:
@Controller
@ControllerAdvice
public class WebSocketGeneralController {
...
@MessageExceptionHandler
public WebSocketMessage handleException(org.springframework.messaging.MessageDeliveryException e) {
WebSocketMessage errorMessage = new WebSocketMessage();
errorMessage.setMessage(e.getClass().getName());
return errorMessage;
}
}
但似乎在任何时候都没有调用方法(尝试捕获不同的异常,只是 Exception 包括 - 没有结果)。我还应该研究什么?
【问题讨论】:
-
同样的问题...您找到解决方案了吗?
标签: java spring spring-security spring-websocket spring-messaging