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

使用Spring WebSocket的SimpMessageTemplate和多endpoint配置

魏波娃
2023-03-14

我将Spring 4.3.5和WebSocket与SockJS、STOMP和SimpleBrokerMessageHandler一起使用。

在我的应用程序中,我有三个独立的WebSocketendpoint在不同的地址上运行:/endPointA、/ednpointB、/endpointC更具体地说,我有三个独立的配置类,用@configuration@EnableWebSocketMessageBroker注释进行注释。

我还有一个类有@Autowired SimpMessageTemplate。

最后,我有三个客户端,每个客户端连接到一个不同的endpoint。然而,他们都订阅了“相同”的频道地址,即/topic/messages

  • ClientOne与endpointA连接

当我使用SimpMessagingTemboard向 /topic/messages发送消息时,所有客户端都会收到此消息。

之后我有两个问题:

  1. 是否有办法隔离Web Socketendpoint,使消息不会传播到所有endpoint?
  2. 为什么这会发生在这里?

我做了一些调查(堆转储分析),发现对于我的配置,我有:

  • SimpMessageTemplate的三个实例,但是我总是使用同一个实例来发送消息(因为@Autowire-另外,我正在打印SimpMessageTemplate.toString()

所以我想知道,这种在所有endpoint上的消息传播是否是SimpleBrokerMessageHandler或SimpMessageTemplate的“功能”。

共有1个答案

年良骏
2023-03-14

我在一个多租户应用程序中遇到了同样的问题,我通过以下线程解决了这个问题:

我的websocketendpoint是:ws://127.0.0.1/My context app/ws,java配置文件是:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {       
      registry.addEndpoint("/ws").setAllowedOrigins("*");
      registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); 
   }
}

我的webSocket队列url表单的前缀是tenant-id:/[tenant-id]/[url-of-队列]

每个客户端都使用自己的租户id进行订阅。由于WebSocketSecurityConfig,它无法订阅另一个客户端的队列。configureInbound(MessageSecurityMetadataSourceRegistry)方法和一个自定义Springbean,它有一个“websocket队列订阅安全检查”方法:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
          .simpSubscribeDestMatchers("/**")
          .access("@customWSSecurityCheck.isSubscriptionAllowed(authentication, message)");
    }

}

我的自定义bean命名为CustWSSecurityCheck,检查是否允许经过身份验证的用户在队列中订阅。请记住,自定义身份验证实现了带有附加tenantId属性的org.springframework.security.core.身份验证,该属性由自定义Spring安全筛选器/身份验证方法上没有提到的附加代码填充:

@Bean()
public class CustomWSSecurityCheck {

    public boolean isSubscriptionAllowed(CustomAuthentication authentication, Message message) {

       StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
       String url = sha.getDestination().substring(1);
       String tenantId = url.substring(0, url.indexOf("/"));

       return tenantId.equals(authentication.getTenantId());
    }
}

当然,它涉及到服务器发送的每条消息都应该以正确的租户id为前缀:MessagingService.convertAndSed("[tenant-id]/[url-of-队列]",MessagePayload)

 类似资料:
  • Spring WebSocket的留档状态为: 应用程序可以发送针对特定用户的消息,为此,Spring的STOMP支持识别前缀为“/user/”的目的地。例如,客户端可能订阅目的地"/user/队列/位置更新"。该目的地将由UserDestinationMessageHandler处理,并转换为用户会话独有的目的地,例如"/队列/位置-更新-用户123"。这提供了订阅通用命名目的地的便利,同时确保

  • 有没有办法在SOAPUI(免费)中配置一个测试用例、测试套件甚至项目级的测试中请求使用的资源/方法? 我们有以下用例: 相同的REST服务在不同的服务器上运行(可能是不同的版本),并且根据配置略有不同的资源路径。 例如或等。 我们希望能够针对这些不同的endpoint/资源组合运行我们的测试套件和测试用例。到目前为止,我们发现更改endpoint的唯一方法是在测试用例级别使用测试用例编辑器,并在测

  • 我最近在Azure存储中遇到了专用endpoint功能,并试图实现它以从VNet进行安全访问。但是,我在同时使用防火墙、虚拟网络服务endpoint和专用endpoint时遇到了访问问题。 我有两个VNet(VNet1 具有启用了服务endpoint功能的子网的VNet1在存储帐户防火墙中被列入白名单 鉴于上述设置,当我尝试访问位于VNet2下的VM内的此存储帐户Blob容器时,我遇到了授权问题。

  • 使用endpointDSL然后用ProducerTemplate引用endpoint的正确方法是什么?当创建路由并使用endpointDSL时,Camel似乎是在为endpoint创建不同的uri。我的EndpointRouteBuilder类:

  • 我是阿帕奇骆驼队的新手。我试图将一个交换从java方法发送到一个路由,但它给了我“由:org.apache.camel.component.direct.DirectConsumerNotAvailableException:endpoint上没有可用的消费者”错误。我想知道这个错误到底是什么,我们什么时候得到这个?

  • 目前正在处理RESTAPI和GraphQL微服务的Express Gateway。GraphQL管道工作得很好,但RESTAPI的管道是我正在努力解决的问题。 我制作了一个简单的CRUD功能RESTAPI,它可以创建、读取、更新和删除书籍和作者。它们有多条路由来实现这一点,例如:http://localhost:4001/books/add。 问题是我并不真正理解如何在快速网关中转换这些路由或路径