gpt4 book ai didi

java - 如何使用 Spring WebSocket 向 STOMP 客户端发送错误消息?

转载 作者:搜寻专家 更新时间:2023-10-30 20:01:51 27 4
gpt4 key购买 nike

我将 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 端点和主题的交互按预期工作。)

在成功连接后,我尝试使用我的 Java 测试客户端订阅 users/{subscribingUsername}/queue/errors 和简单的 users/queue/errors,但到目前为止,我一直无法从发送到客户端的服务器中获取有关订阅异常的错误消息。这显然不太理想,因为从未通知客户他们已被拒绝访问。

最佳答案

你不能只从 clientInboundChannel 上的 MySubscriptionInterceptor 抛出异常,因为最后一个是 ExecutorSubscribableChannel,因此是 async 和来自这些线程的任何异常最终都会出现在日志中,并会重新抛给调用者 - StompSubProtocolHandler.handleMessageFromClient

但是你可以做的是像 clientOutboundChannel 这样的东西并像这样使用它:

StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.ERROR);
headerAccessor.setMessage(error.getMessage());

clientOutboundChannel.send(MessageBuilder.createMessage(new byte[0], headerAccessor.getMessageHeaders()));

要考虑的另一个选项是注释映射:

    @SubscribeMapping("/foo")
public void handleWithError() {
throw new IllegalArgumentException("Bad input");
}

@MessageExceptionHandler
@SendToUser("/queue/error")
public String handleException(IllegalArgumentException ex) {
return "Got error: " + ex.getMessage();
}

关于java - 如何使用 Spring WebSocket 向 STOMP 客户端发送错误消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33741511/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com