如何在订阅频道时检查websocket用户是否已通过身份验证?

问题描述 投票:0回答:1

我有websocket配置类:

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableSimpleBroker("/topics");
            config.setApplicationDestinationPrefixes("/app");        
    }

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

ClientInboundChannel一样:

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(new ChannelInterceptorAdapter() {

        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {

            StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

            final String xAuthToken = accessor.getFirstNativeHeader(ManipulatesHeaders.X_AUTH_TOKEN_HEADER);

            if (xAuthToken == null) {
                return message;
            }

            final UserDetails userDetails = authService.getUserDetails(xAuthToken);

            if (StompCommand.CONNECT == accessor.getCommand()) {
                final WebSocketPrincipal principal = (...)

                userRegistry.registerUser(principal, message);
                accessor.setUser(principal);
            }

            return message;
        }
    }
}

现在,我想向订阅特定频道的每个用户发送欢迎消息。很明显,可以通过创建一个实现ApplicationListener<SessionSubscribeEvent>并提供的类来实现

@Override
    public void onApplicationEvent(final SessionSubscribeEventevent) {
      StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());
}

第二种方法是在上述ClientInboundChannel中执行类似的事情(它是相同的)。

问题是,当用户发送staz simpUser时,message中没有SUBSCRIBE标头。

过程如下:用户发送stomp CONNECT,执行此行:accessor.setUser(principal),此时message已正确设置simpUser标头。但是当在SUBSCRIBE收到stomp preSend消息时,StompHeaderAccessor没有simpUser标题。因此,我无法评估用户是否已经过身份验证。

那么如何检查发送SUBSCRIBE消息的用户是否已经过身份验证? (以及为什么经过身份验证的用户不会发送simpUser标头)

java spring spring-mvc websocket spring-websocket
1个回答
1
投票

在您的websocket配置类中,将您的扩展名更改为AbstractSecurityWebSocketMessageBrokerConfigurer

然后您可以按如下方式设置安全性:

@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry message) {
    message
      .nullDestMatcher().permitAll()
      .simpDestMatchers("/app/**").authenticated()
      .simpSubscribeDestMatchers("/topics/**").authenticated()
      .anyMessage().denyAll();
}

如果你得到错误Could not verify the provided CSRF token because your session was not found你将不得不覆盖websocket配置类中的`sameOriginDisabled

  @Override
  protected boolean sameOriginDisabled() {
      return true;
  }

有关websocket安全性的更多信息:

https://docs.spring.io/spring-security/site/docs/current/reference/html/websocket.html

© www.soinside.com 2019 - 2024. All rights reserved.