ReactiveSecurityContextHolder # getContext возвращает пустой контекст - PullRequest
0 голосов
/ 19 сентября 2019

Я пытаюсь аутентифицировать пользователя (это работает) и получить токен пользователя из контекста, и это не работает.

У меня есть простое микросервисное приложение в качестве моего домашнего проекта, и я использую 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

1 Ответ

0 голосов
/ 19 сентября 2019

Итак, после исследования и отладки я обнаружил причину использования объединения потоков в один.ИМХО, это не совсем причина этой проблемы, но теперь она работает.

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