繁体   English   中英

如何在反应式 webflux 中获取 spring 安全上下文

[英]How to get spring security context in reactive webflux

我的 spring 启动应用程序(版本 2.6.3)有问题。 我已经像那里那样配置了反应式 spring 安全性:

我的应用程序.java:

@SpringBootApplication
@EnableWebFlux
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class);
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http, final ReactiveOpaqueTokenIntrospector reactiveOpaqueTokenIntrospector) {
        return http.authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .httpBasic().disable()
                .cors().and()
                .logout().disable()
                .formLogin().disable()
                .oauth2ResourceServer()
                .opaqueToken()
                .introspector(reactiveOpaqueTokenIntrospector)
                .and().and()
                .csrf()
                .disable()
                .build();
    }
    
}

这是我的 web 资源(控制器):

我的网络资源.java:

@RestController
public class MyWebResource implements MyWebResourceApi {

    
    @PreAuthorize("hasRole('ROLE_USER')")
    @Override
    public Mono<String> details(String userId, ServerWebExchange exchange) {
        return exchange.getPrincipal().map(Principal::getName);
    }
}

它工作正常,当我的访问令牌过期或不正确时,应该拒绝请求。 但是,当 PreAuthorized 允许请求时,我的用户主体将永远不会在我的交换中得到解决...

在反应式应用程序中,身份验证信息存储在反应式流程中,可以从Mono / Flux访问。 您可以使用ReactiveSecurityContextHolder获取当前经过身份验证的主体或身份验证请求令牌。

@PreAuthorize("hasRole('ROLE_USER')")
public Mono<String> details() {
        return ReactiveSecurityContextHolder.getContext()
                .map(ctx -> ((Principal) ctx.getAuthentication().getPrincipal()).getName());
    }

我找到了这个答案,寻找一种将访问令牌添加到我的网络客户端请求的方法。 如果我们使用 OAuth2 或 OpenID Connect 并且想要访问令牌而不是委托人的名称,那么通过安全上下文中的委托人这是不可能的。

相反,我们需要创建一个ServerOAuth2AuthorizedClientExchangeFilterFunction并将其注册为 WebClient 的过滤器 function:

ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
    new ServerOAuth2AuthorizedClientExchangeFilterFunction(
        clientRegistrations,
        authorizedClients);

        oauth.setDefaultOAuth2AuthorizedClient(true);

其中clientRegistrationsReactiveClientRegistrationRepository类型的可注入 bean, authorizedClientsServerOAuth2AuthorizedClientRepository类型的可注入 bean。

然后我们可以使用构建器的filters方法将我们的过滤器 function 添加到exchangeFilterFunctions

WebClient.builder()
         .filters(exchangeFilterFunctions -> {
                    exchangeFilterFunctions.add(oauth);
                  })
         .build();

Baeldung 有一篇关于此的很好的背景文章,更详细地解释了它: https://www.baeldung.com/spring-webclient-oauth2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM