如何在 Spring Websocket 支持但没有 STOMP 的情况下使用 Spring 安全性?

How to use Spring Security with Spring Websocket support but without STOMP?

我目前正在构建一个 Web 应用程序,该应用程序使用 Spring 来利用 websocket 支持和安全性。问题是,我不想使用 STOMP。它现在大约有 4 个没有更新,我不需要它。所以我按照另一个 Whosebug question 的答案为带有 SockJS 但没有 STOMP 的 websockets 配置 Spring。

现在我想集成 Spring websocket 身份验证和授权的安全性。不幸的是,documentation 必须为 STOMP-websockets 配置 Spring 安全性。

如果您能帮助我配置 Spring 安全性,我将不胜感激。有人可能知道任何教程或示例吗?我还没有找到。

Websocket 消息传递会话以 Http 请求开始,因此 spring 安全性可以用作保护 http 请求的框架。在 spring 中,经过安全身份验证的用户及其关联的安全上下文存储在会话中。 Authenticated 可以从 Websocket 握手访问,因为它传输 http 请求。 Spring Websocket 定义了 HttpSessionHandshakeInterceptor,可以使用 addInterceptors 方法在您的配置中注册它

    @EnableWebSocket
    @Configuration
    public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry 
       webSocketHandlerRegistry) {
    webSocketHandlerRegistry.addHandler(createHandler(), 
    "/handler").addInterceptors(new HttpSessionHandshakeInterceptor() 
      {
        @Override
        public void afterHandshake(ServerHttpRequest request, 
         ServerHttpResponse response, WebSocketHandler wsHandler, 
         @Nullable Exception ex) {

            super.afterHandshake(request, response, wsHandler, ex);

        }

        @Override
        public boolean beforeHandshake(ServerHttpRequest request, 
         ServerHttpResponse response, WebSocketHandler wsHandler, 
          Map<String, Object> attributes) throws Exception {
            boolean b = super.beforeHandshake(request, response, 
         wsHandler, attributes) && 
      ((UsernamePasswordAuthenticationToken) 
    request.getPrincipal()).isAuthenticated();
            return b;
        }
         }).withSockJS();
    }

     @Bean
     public WebSocketHandler createHandler() {

    return new MyHandler();

    }
   }

您还可以在存储在 websocket 会话中的处理程序中验证经过身份验证的使用

我只会添加上面的答案,指定我设法解决它。

我的问题是 request.getPrinciple() 返回了 null。从标题的观看播放后,我发现 cookie 值。并将相同的 cookie id 值替换为 websocket 请求,服务器找到此请求的 principle

例如,当我们授权时,我向/auth/principal发出请求,以从数据库中获取有关玩家的数据。

@GetMapping(value="/auth/principal")
    public ResponseEntity principal(HttpServletRequest request,
                                    Principal principal) {
        Player player = playerService.findByEmail(principal.getName());

        String jsonString = new JSONObject()
                .put("id", player.getId())
                .put("nickname", player.getNickname())
                .put("cookie", request.getHeader("cookie")).toString();

        return new ResponseEntity(jsonString, HttpStatus.OK);
    }

然后,在客户端,当我想连接到 websocket 时,我指定请求的 headers,定义 cookie (cookie: COOKIE-ID)