【问题标题】:ReactiveSecurityContextHolder#getContext returns an empty contextReactiveSecurityContextHolder#getContext 返回一个空的上下文
【发布时间】:2020-01-20 11:25:34
【问题描述】:

我尝试对用户进行身份验证(它有效)并从上下文中获取用户令牌,但它不起作用。

我有一个简单的微服务应用程序作为我的宠物项目,并使用 WebFlux 作为网络框架。我尝试调试 ReactiveSecurityContextHolder#getContext 并在 flatMap 内部看到我的用户令牌在上下文中,但在我的应用程序中我有一个空上下文。

SecurityConfiguration.java

@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(
            AuthenticationWebFilter authenticationWebFilter,
            ServerHttpSecurity http) {
        return http
                .csrf().disable()
                .httpBasic().disable()
                .formLogin().disable()
                .logout().disable()
                .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .build();
    }

    @Bean
    public AuthenticationWebFilter authenticationWebFilter(
            SecurityTokenBasedAuthenticationManager authenticationManager,
            TokenAuthenticationConverter tokenAuthenticationConverter) {
        AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(authenticationManager);

        authenticationWebFilter.setServerAuthenticationConverter(tokenAuthenticationConverter);
        authenticationWebFilter.setSecurityContextRepository(new WebSessionServerSecurityContextRepository());

        return authenticationWebFilter;
    }
}

ReactiveAuthenticationManager.java

@Slf4j
@Component
@AllArgsConstructor
public class SecurityTokenBasedAuthenticationManager implements ReactiveAuthenticationManager {

    private final AuthWebClient authWebClient;

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {

        return Mono.just(authentication)
                .switchIfEmpty(Mono.defer(this::raiseBadCredentials))
                .cast(Authorization.class)
                .flatMap(this::authenticateToken)
                .map(user ->
                        new Authorization(user, (AuthHeaders) authentication.getCredentials()));
    }

    private <T> Mono<T> raiseBadCredentials() {
        return Mono.error(new TokenValidationException("Invalid Credentials"));
    }

    private Mono<User> authenticateToken(Authorization authenticationToken) {
        AuthHeaders authHeaders = (AuthHeaders) authenticationToken.getCredentials();
        return Optional.of(authHeaders)
                .map(headers -> authWebClient.validateUserToken(authHeaders.getAuthToken(), authHeaders.getRequestId())
                        .doOnSuccess(user -> log
                                .info("Authenticated user " + user.getUsername() + ", setting security context")))
                .orElseThrow(() -> new MissingHeaderException("Authorization is missing"));
    }
}

SecurityUtils.java

@Slf4j
public class SecurityUtils {

    public static Mono<AuthHeaders> getAuthHeaders() {
        return getSecurityContext()
                .map(SecurityContext::getAuthentication)
                .map(Authentication::getCredentials)
                .cast(AuthHeaders.class)
                .doOnSuccess(authHeaders -> log.info("Auth headers: {}", authHeaders));
    }

    private static Mono<SecurityContext> getSecurityContext() {
        return ReactiveSecurityContextHolder.getContext();
    }
}

WebClient 构建

(...)
WebClient.builder()
                .baseUrl(url)
                .filter(loggingFilter)
                .defaultHeaders(httpHeaders ->
                        getAuthHeaders()
                                .doOnNext(headers -> httpHeaders.putAll(
                                        Map.of(
                                                REQUEST_ID, singletonList(headers.getRequestId()),
                                                AUTHORIZATION, singletonList(headers.getAuthToken())))))
                .build()
(...)

主要问题是在我的 WebClient 的构建内部 - 我希望,我将拥有带有请求标头的完整 webclient,但如上所述 - 我在 SecurityUtils.java 中有一个空上下文

【问题讨论】:

    标签: java spring spring-security spring-webflux


    【解决方案1】:

    因此,在调查和调试之后,我发现了将流合并为单个流的原因。恕我直言,这不是导致此问题的完全原因,但现在它可以工作了。

    (...)
    getAuthHeaders()
        .flatMap(authHeaders -> buildWebClient(url, authHeaders)
                      .get()
    (...)
    

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 2013-09-14
      • 1970-01-01
      • 2018-04-26
      • 2013-03-18
      • 2013-06-03
      • 2015-12-03
      • 2011-09-07
      • 1970-01-01
      相关资源
      最近更新 更多