如何在 Spring WebFlux 中获取当前经过身份验证的用户

发布于 2025-01-12 04:33:39 字数 2567 浏览 6 评论 0原文

我正在尝试检索身份验证对象,该对象创建用户名和权限。 我知道在 WebFlux 中我不能使用 SecurityContextHolder.getContext(),而是必须使用 ReactiveSecurityContextHolder.getContext()

但在这两种情况下,结果均为 null。

        val autx = ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication) // always null

或者

        val auth = ReactiveSecurityContextHolder.getContext().filter { it.authentication != null }
            .map { it.authentication.principal }.block() // always null

我理解,在从 ReactiveSecurityContextHolder 检索 auth 对象之前,必须有人将其放入其中。找不到任何示例如何执行此操作以及应在代码中的何处填充它。 理想情况下,我认为它应该在authenticate方法中的ReactiveAuthenticationManager实现中。
我将其添加到authenticate方法中:

                ReactiveSecurityContextHolder.getContext()
                    .map { context: SecurityContext ->
                        context.authentication.principal
                    }
                    .cast(UserData::class.java)
                    .contextWrite(ReactiveSecurityContextHolder.withAuthentication(authentication))
                    .subscribe()

但它不会改变任何

Java或Kotlin上的工作示例值得赞赏的

配置:

@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
    return http.authorizeExchange()
        .pathMatchers("**/health").permitAll()
        .pathMatchers("/**").authenticated()
        .anyExchange().authenticated()
        .and()
        .authenticationManager(authenticationManager) // ReactiveAuthenticationManager impl
        .securityContextRepository(securityContextRepository)
        .csrf().disable()
        .cors().configurationSource(corsConfig())
        .and()
        .build()
}

上下文存储库:

@Component
class SecurityContextRepository(
    val authenticationManager: ReactiveAuthenticationManager
) : ServerSecurityContextRepository {

    override fun save(swe: ServerWebExchange, sc: SecurityContext): Mono<Void> {
        throw UnsupportedOperationException("SecurityContext save not supported")
        // if i want to save, what should be there? 
    }

    override fun load(serverExchange: ServerWebExchange): Mono<SecurityContext> {
        val authHeader = serverExchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)
        val preAuthentication = PreAuthenticatedAuthenticationToken(null, authHeader)
        return this.authenticationManager.authenticate(preAuthentication)
            .map { authentication -> SecurityContextImpl(authentication) }
    }
}

I'm trying to retrieve authentication object, which creates user name and permissions.
I know that in WebFlux I cannot use SecurityContextHolder.getContext(), but rather must use ReactiveSecurityContextHolder.getContext()

But in both cases, result is null.

        val autx = ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication) // always null

or

        val auth = ReactiveSecurityContextHolder.getContext().filter { it.authentication != null }
            .map { it.authentication.principal }.block() // always null

I understand, that before retrieve auth object from ReactiveSecurityContextHolder, someone must put it into there. Cannot find any example how to do that, and where in the code it should be populated.
Ideally, I think it should be in the ReactiveAuthenticationManager implementation in the authenticate method.
I added this into authenticate method:

                ReactiveSecurityContextHolder.getContext()
                    .map { context: SecurityContext ->
                        context.authentication.principal
                    }
                    .cast(UserData::class.java)
                    .contextWrite(ReactiveSecurityContextHolder.withAuthentication(authentication))
                    .subscribe()

but it doesnt change anything

working examples on Java or Kotlin are appreciated

configuration:

@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
    return http.authorizeExchange()
        .pathMatchers("**/health").permitAll()
        .pathMatchers("/**").authenticated()
        .anyExchange().authenticated()
        .and()
        .authenticationManager(authenticationManager) // ReactiveAuthenticationManager impl
        .securityContextRepository(securityContextRepository)
        .csrf().disable()
        .cors().configurationSource(corsConfig())
        .and()
        .build()
}

context repository:

@Component
class SecurityContextRepository(
    val authenticationManager: ReactiveAuthenticationManager
) : ServerSecurityContextRepository {

    override fun save(swe: ServerWebExchange, sc: SecurityContext): Mono<Void> {
        throw UnsupportedOperationException("SecurityContext save not supported")
        // if i want to save, what should be there? 
    }

    override fun load(serverExchange: ServerWebExchange): Mono<SecurityContext> {
        val authHeader = serverExchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)
        val preAuthentication = PreAuthenticatedAuthenticationToken(null, authHeader)
        return this.authenticationManager.authenticate(preAuthentication)
            .map { authentication -> SecurityContextImpl(authentication) }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

明月松间行 2025-01-19 04:33:39

您需要使用 SecurityWebFilterChain bean 定义 WebFlux 安全配置。以下是 OAuth 2.0 资源服务器的示例:

@Bean
public SecurityWebFilterChain apiSecurity(ServerHttpSecurity http) {
    http.authorizeExchange()
            .pathMatchers("/api/**").hasAuthority("SCOPE_api")
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
    return http.build();
}

您可以在此处找到更多详细信息 WebFlux 安全

You need to define WebFlux Security configuration using SecurityWebFilterChain bean. Here is an example for OAuth 2.0 Resource Server:

@Bean
public SecurityWebFilterChain apiSecurity(ServerHttpSecurity http) {
    http.authorizeExchange()
            .pathMatchers("/api/**").hasAuthority("SCOPE_api")
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
    return http.build();
}

You can find more details here WebFlux Security

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文