2

我写了一个小项目,它使用带有 Websockets 和 RabbitMQ 作为代理的 Spring MVC 4。我正在尝试发回给单个用户(convertAndSendToUser),但我似乎无法让它工作。这是应用程序的作用:

  1. 通过 HTTP 向 Spring Security 进行身份验证。身份验证通过 AJAX 进行,后端为每个新连接分配一个 UUID 作为用户名。可能有多个客户端使用相同的用户名,所以我希望能够针对单个浏览器,尽管它们可能使用相同的用户名登录
  2. 在通过 AJAX 进行身份验证后,webapp 使用 STOMP over Websockets 连接到 API。这些是在 CONNECT FRAME 中发回的标头

    正文:"" 命令:"CONNECTED" 标头:对象心跳:"0,0" 服务器:"RabbitMQ/3.3.1" 会话:"session-OGzAN6T8Y0X9ft3Jq04fiQ" 用户名:"88dc9424-72e3-4814-be8c- e31dbf89b521" 版本:"1.1"

如您所见,没有frame-suffix或 session-id 字段。

  1. 当我从后端使用 convertAndSendToUser 时,响应会发送到一个独特的队列,例如:/exchange/jobs-userh6g_48h9。队列名称是 /exchange/jobs 但 Spring 自动附加后缀-userh6g_48h9。用户名是“user”,sessionId 是“h6g_48h9” 这很好,我想要这种行为,但问题是客户端(webapp)在 CONNECT 框架中没有得到这个会话 id,没有办法让它实际上订阅了那个独特的队列。

如何解决这个问题?我希望在连接时将队列后缀/会话 ID 发送回给我,以便客户端可以获取此后缀并订阅他的唯一队列。由于缺乏信息,目前没有消息从服务器返回。

4

1 回答 1

0

如果我错了,请纠正我,但由于 UserDestinationMessageHandler,客户端应该能够订阅,/user/exchange/jobs并且该消息处理程序将为您更正队列名称。

作为旁注,您还应该考虑添加一个扩展 AbstractSecurityWebSocketMessageBrokerConfigurer 的配置类,类似于以下内容:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
                .antMatchers(SimpMessageType.MESSAGE, "/topic/**", "/queue/**").denyAll() // Prevent users sending messages directly to topics and queues
                .antMatchers(SimpMessageType.SUBSCRIBE, "/queue/**/*-user*", "/topic/**/*-user*").denyAll() // Prevent users from subscriptions to private queues
                .antMatchers("/user/queue/errors").permitAll()
                .anyMessage().hasRole("ANY_OPTIONAL_ROLE_ETC")
        ;
    }
}

这将防止“有进取心”的用户订阅他们不应该订阅的东西。

于 2015-02-27T06:20:13.160 回答