当前位置: 首页 > 知识库问答 >
问题:

如何使用SpringWebSocket向STOMP客户端发送错误消息?

艾星河
2023-03-14

我使用Spring的STOMP over WebSocket实现与一个全功能的ActiveMQ代理。当用户向主题订阅SUBSCRIBE时,在成功订阅之前必须通过一些权限逻辑。我使用ChannelInterceptor应用权限逻辑,如下所示:

WebSocketConfig。爪哇:

@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。爪哇:

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 checkPermisshtml" target="_blank">ions(Principal principal) {
    // apply permissions logic
    // throw Exception permissions not sufficient
  }
}

当没有足够权限的客户端尝试订阅受限制的主题时,他们实际上从未收到来自该主题的任何消息,但也不会被通知抛出拒绝订阅的异常。相反,客户端被退回一个死订阅,而ActiveMQ代理对此一无所知。正常的、充分许可的客户端与STOMPendpoint和主题的交互与预期的一样工作。)

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

共有1个答案

微生信鸿
2023-03-14

你不能只是抛出异常从MySubcriptionInterceptor上的clientInundChannel,因为最后一个是ExecutorSubcribableChannel,因此是async和任何异常从这些线程结束在日志中与任何re-抛给调用方-StompSub原型colHandler.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();
    }

 类似资料:
  • 问题内容: 我从socket.io + node.js开始,我知道如何在本地发送消息和广播功能:-所有连接的客户端都收到相同的消息。 现在,我想知道如何向特定的客户端发送私人消息,我的意思是一个套接字,用于2个人之间的私人聊天(客户端到客户端流)。谢谢。 问题答案: 当用户连接时,它应使用唯一的用户名(例如电子邮件)向服务器发送消息。 一对用户名和套接字应存储在这样的对象中: 在客户端上,使用以下

  • 我有一个Spring Boot服务器和一个客户端,它们使用STOMP通过Websockets连接。 我的用例是,每次向特定endpoint发出http请求时,我都想向客户机发送数据。我找到的所有教程,只展示了这种情况,客户端向“/hello”发送一些数据,服务器通过向“topic/greetings”发送数据做出反应: 我需要的是一个控制器方法,它无需消息映射即可发送数据。它应该只是在每次有人对e

  • 我需要一个推送消息服务器的方案。 现在我选择AutobahnJs+AutobahnPython方案。 AutobahnJs库使用html5的websocket连接AutobahnPython使用的服务器 在javascript中,使用订阅通道,每个客户端使用相同的订阅通道。clientD将消息发布到通道(与订阅通道相同),服务器将消息传递给订阅该通道的所有客户端。 这里有一个问题,我需要应用程序(

  • 我尝试将Spring与websocket一起使用。我从本教程开始调查。 在我的侧客户端,我有类似的东西来初始化到服务器的连接: 它工作得很好,在我的控制器中,我可以在下面的类中执行我的过程: 现在我想做的是让一个线程向监听“/主题/问候”的客户端发送消息。我这样写Runnable类: 这样完成了我的控制器: 该方法采用光电控制器。fireGreeting按我的要求调用,但客户端没有发生任何事情。有

  • 问题内容: 我正在使用Java开发RESTful Web服务。如果出现问题,我需要一种将错误消息发送给客户端的好方法。 根据Javadoc的规定, “由于message参数含义不明确 ,因此不建议使用 ”。 有没有设置状态消息或响应的“ 原因短语 ”的首选方法?该方法不这样做。 编辑:为了澄清,我想修改HTTP状态行,即不是主体内容。具体来说,我想发送类似的回复。 问题答案: 我认为任何RESTf

  • 我有一个ASP.NET Core1.0Web API应用程序,并试图弄清楚如果我的控制器调用的函数出错,如何将异常消息传递给客户端。 我确实看到了一些使用的文档,但是为了使用它,我必须安装compat shim。在Core1.0中有没有一种新的方法来做这些事情? 这是我一直在尝试的垫片,但它不起作用: 当抛出时,我查看客户端,在内容中找不到我正在发送的消息。