【问题标题】:Multiple rooms authorisation with Spring WebSocket and security使用 Spring WebSocket 和安全性进行多房间授权
【发布时间】:2020-10-23 05:42:26
【问题描述】:

我正在使用用户授权进行多房间聊天:用户只能访问某些分配的房间。

为每个房间创建一个具有唯一房间 ID 的主题

如何在打开套接字进行读取期间检查权限?

在服务器端,对于新的入站连接,我想从主题 URL 获取房间 ID 并检查房间的用户访问权限。但我没有找到我该怎么做。我没看到这个地方,有可能。

AbstractSecurityWebSocketMessageBrokerConfigurer -- 无法动态检查

@Configuration
class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

   @Override
   protected void configureInbound(MessageSecurityMetadataSourceRegistry message) {
       message.nullDestMatcher().permitAll()
            .simpDestMatchers("/app/**").authenticated()
            .anyMessage().hasRole("USER")
   }
}

WebSocketMessageBrokerConfigurer -- 无法获取当前网址

@Configuration
class WebSocketSecurityConfig extends WebSocketMessageBrokerConfigurer {


@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.interceptors(new ChannelInterceptor() {
        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
            if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {
               ...
            }
            return message
        }
    });
}
}

我知道,如何在写入消息期间检查访问权限,但找不到,如何在打开 Web 套接字进行读取期间进行检查。这种情况的标准机制是什么?

依赖关系:

compile 'org.grails.plugins:grails-spring-websocket:2.5.0.RC1'
compile "org.springframework.security:spring-security-messaging"
compile "org.springframework.security:spring-security-config" 
compile "org.springframework.security:spring-security-core:5.1.8.RELEASE"
compile "org.springframework:spring-messaging:5.1.6.RELEASE"

更新

我可以从客户端传递房间 ID 作为标头,但在服务器上 configureClientInboundChannel 我不能确定标头中的房间 ID 是否与主题 URL 中的 ID 相同。我可以使用一些在服务器端生成的哈希,但它看起来太复杂了

var socket = new SockJS("${createLink(uri: '/stomp')}");
var client = webstomp.over(socket);

client.connect({room-id:"0"}, function() {
   client.subscribe("/topic/room/1", function(message) {
       console.log("/topic/room/1");
   }, {roomId:"1"});

client.subscribe("/topic/room/2", function(message) {
       console.log("/topic/room/2");
   }, {roomId:"2"});                
});

【问题讨论】:

    标签: spring-security spring-websocket


    【解决方案1】:

    在调试过程中,我检查了 StompCommand.CONNECT 类型的命令头。

    对于 StompCommand.SUBSCRIBE 命令,当前主题 URL 显示在 simpDestination 标头

    最终解决方案是:

    @Configuration
    class WebSocketSecurityConfig extends WebSocketMessageBrokerConfigurer {
    
    
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {
                   def currentAuthentication = accessor.getHeader('simpUser') // from spring security 
                   String destinationUrl = (String )accessor.getHeader('simpDestination')
                   // do check, and throw AuthenticationException   
                }
                return message
            }
        });
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-05-10
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      • 2015-04-24
      • 2018-02-10
      • 1970-01-01
      相关资源
      最近更新 更多