spring-security Spring RSocket over WebSocket -从HTTP会话访问用户信息

5ktev3wc  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(146)

在我的Web应用程序中,用户使用用户名/密码组合登录,并获得会话cookie。当启动WebSocket连接时,我可以轻松访问WebSocketHandler中的用户信息,例如:

@Component
public class MyWebSocketHandler implements WebSocketHandler {
    @Override
    public Mono<Void> handle(WebSocketSession session) {
        // two ways to access security context information, either like this:
        Mono<Principal> principal = session.getHandshakeInfo().getPrincipal();

        // or like this
        Mono<SecurityContext> context = ReactiveSecurityContextHolder.getContext();

        //...
        return Mono.empty();
    }
}

两者都重用来自WebSocket握手的HTTP会话,我不需要通过WebSocket本身发送额外的身份验证。我可以重用HTTP会话的信息。
如何使用RSocket实现同样的功能?例如,如何在MessageMapping方法中获取用户信息,如下所示?

@Controller
public class RSocketController {
    @MessageMapping("test-stream")
    public Flux<String> streamTest(RSocketRequester requester) {
        // this mono completes empty, no security context available :(
        Mono<SecurityContext> context = ReactiveSecurityContextHolder.getContext();

        return Flux.empty();
    }
}

我找到了许多如何使用RSocket设置身份验证的资源,但它们都依赖于在建立WebSocket连接后的额外身份验证,但我特别希望重用Web会话,不希望通过WebSocket发送额外的令牌。

xxls0lw8

xxls0lw81#

您是否尝试过以下方法?我在文档中找到了这些方法:2.2保护您的RSocket方法(可能需要向下滚动一点)https://spring.io/blog/2020/06/17/getting-started-with-rsocket-spring-security

@PreAuthorize("hasRole('USER')") // (1)
@MessageMapping("fire-and-forget")
public Mono<Void> fireAndForget(final Message request, @AuthenticationPrincipal UserDetails user) { // (2)
    log.info("Received fire-and-forget request: {}", request);
    log.info("Fire-And-Forget initiated by '{}' in the role '{}'", user.getUsername(), user.getAuthorities());
    return Mono.empty();
}
oo7oh9g9

oo7oh9g92#

您可以使用@AuthenticationPrincipal Mono<UserDetails> userDetails获取用户信息。
如果有人像我一样使用JWT身份验证,则需要将@AuthenticationPrincipal Mono<Jwt> jwt添加到方法参数中。
但要使其正常工作,您需要配置RSocketMessageHandler bean,它解析参数。

@Bean
public RSocketMessageHandler rSocketMessageHandler(RSocketStrategies strategies) {
    RSocketMessageHandler handler = new RSocketMessageHandler();
    handler.getArgumentResolverConfigurer()
            .addCustomResolver(new AuthenticationPrincipalArgumentResolver());
    handler.setRSocketStrategies(strategies);
    return handler;
}

重要的是,你必须使用org.springframework.security.messaging.handler.invocation.reactive.AuthenticationPrincipalArgumentResolver()类作为解析器,为此你需要spring-security-messaging依赖项。

相关问题