【问题标题】:Spring WebFlux authenticated WebSocket connectionSpring WebFlux 认证的 WebSocket 连接
【发布时间】:2020-03-12 17:23:09
【问题描述】:

我正在运行带有暴露 WebSocket 端点的 Spring Boot@2.2.x 服务器。这是我的WebSocketConfiguration

@Slf4j
@Configuration
public class WebSocketConfiguration {

    private static final String WS_PATH = "/ws/notifications";

    @Bean
    public HandlerMapping webSocketHandlerMapping() {
        Map<String, WebSocketHandler> handlersMap = new HashMap<>();
        handlersMap.put(WS_PATH, session -> session.send(session.receive()
                                                                .map(WebSocketMessage::getPayloadAsText)
                                                                .doOnEach(logNext(log::info))
                                                                .map(msg -> format("notification for your msg: %s", msg))
                                                                .map(session::textMessage)));

        SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
        handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
        handlerMapping.setUrlMap(handlersMap);
        return handlerMapping;
    }

    @Bean
    public WebSocketHandlerAdapter handlerAdapter(WebSocketService webSocketService) {
        return new WebSocketHandlerAdapter(webSocketService);
    }

    @Bean
    public WebSocketService webSocketService() {
        return new HandshakeWebSocketService(new ReactorNettyRequestUpgradeStrategy());
    }
}

问题是如何使用Basic AuthenticationBearer Authenticationaccess_token 查询参数来实现建立WS 连接的身份验证?

最好的选择是避免使用 Spring Security。

谢谢。

【问题讨论】:

    标签: spring-boot websocket spring-webflux spring-websocket java-websocket


    【解决方案1】:

    Websocket 连接以 Upgraded 的 HTTP 请求开始。您可以在升级之前进行 JWT 令牌身份验证。在 Spring Boot 中,它的工作原理如下:

    公开一个自定义的WebSocketService bean:

    @Bean
    public WebSocketService webSocketService(RequestUpgradeStrategy upgradeStrategy) {
        return new HandshakeWebSocketService(upgradeStrategy);
    }
    

    在你自己的类中实现RequestUpgradeStrategy接口:

    @Override
    public Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler handler, @Nullable String subProtocol, Supplier<HandshakeInfo> handshakeInfoFactory) {
        ServerHttpResponse response = exchange.getResponse();
        HttpServerResponse reactorResponse = getNativeResponse(response);
        HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
        NettyDataBufferFactory bufferFactory = (NettyDataBufferFactory) response.bufferFactory();
    
        var authResult = validateAuth(handshakeInfo);
        if (authResult == unauthorised) return Mono.just(reactorResponse.status(rejectedStatus))
                                                   .flatMap(HttpServerResponse::send);
        else return reactorResponse.sendWebsocket(subProtocol, //
                                                  this.maxFramePayloadLength,//
                                                  (in, out) -> {
                                                      ReactorNettyWebSocketSession session = new ReactorNettyWebSocketSession(in, out,
                                                                                                                              handshakeInfo,
                                                                                                                              bufferFactory,
                                                                                                                              this.maxFramePayloadLength);
                                                      return handler.handle(session);
                                                  });
    }
    

    注意事项:

    • 以上类基于ReactorNettyRequestUpgradeStrategy

    • 返回 reactorResponse.sendWebsocket 是将连接升级为 WebSocket 连接的现有行为

    • 可以返回reactorResponse.status 以停止正在升级的连接。例如,您可以在未授权连接的情况下返回401 响应。

    • 查询参数和Authentication 标头可以在握手信息中找到。如何进行身份验证本身超出了问题的范围。

    【讨论】:

      猜你喜欢
      • 2020-11-05
      • 2018-05-07
      • 2020-03-15
      • 2022-08-06
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 1970-01-01
      相关资源
      最近更新 更多