[FIXED] Webflux mit verschiedenen Authentifizierungsschemata

Ausgabe

Ich habe gerade ein Projekt erhalten, das ich warten muss, und ich muss Unterstützung für ein zusätzliches Authentifizierungsschema in einem Ressourcenserver hinzufügen. So etwas wie ein normales Authentication: Bearer <jwt.token>, um ein benutzerdefiniertes zu verwenden: Authentication: Custom <other.jwt.token>. Beide sollten unterschiedlich funktionieren und gehandhabt werden.

Ja, ich weiß, dass Spring mit mehreren Anbietern umgehen kann, ich weiß, dass ich einen ReactiveAuthenticationManager verwenden kann, aber ich stecke fest, wie ich mit dem CustomPräfix für das undurchsichtige Token umgehen soll.

Nur um es klar zu stellen, ich brauche beide, um zu funktionieren – und natürlich anders gehandhabt zu werden:

GET /
Authorization: Bearer x.y.z

und

GET /
Authorization: Custom a.b.c

Wenn möglich, möchte ich auch die Liste der unterstützten Authentifizierungsprotokolle im WWW-AuthorizationHeader (dh Bearer, Custom) zurückgeben.

Irgendwelche Hinweise? Googeln zeigt mich nur auf normales Zeug, mit Bearer und was auch immer ich versuche, lehnt Spring mich automatisch mit 401 ab (Token wird natürlich nicht behandelt).

Vielen Dank.

Lösung

Was ich getan habe:

  • Ich habe verschiedene implementiert ReactiveAuthenticationManager, eine für jedes Protokoll, das ich brauchte. So etwas wie BearerReactiveAuthenticationManagerund CustomReactiveAuthenticationManagerund machte sie @Components;
  • ServerSecurityContextRepositoryIch habe auch beide Authentifizierungsmanager aus dem vorherigen Punkt implementiert und injiziert. Im Körper hatte ich so etwas wie:
    @Override
    public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) {
        ServerHttpRequest request = serverWebExchange.getRequest();
        String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);

        if (authHeader.startsWith("Bearer ")) {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.bearerReactiveAuthenticationManager.authenticate(auth)
                    .map(SecurityContextImpl::new);
        } else if (authHeader.startsWith("Custom ")) { {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.customReactiveAuthenticationManager.authenticate(auth)
                    .map(SecurityContextImpl::new);
        } else {
            log.debug("Could not identify the authentication header");
            return Mono.empty();
        }
    }

Und meine SecurityConfig-Bean sah so aus:

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Slf4j
public class SecurityConfig {

    private final ServerSecurityContextRepository serverSecurityContextRepository;

    @Autowired
    public SecurityConfig(ServerSecurityContextRepository serverSecurityContextRepository) {
        this.serverSecurityContextRepository = serverSecurityContextRepository;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable()
                .securityContextRepository(serverSecurityContextRepository)
                .exceptionHandling()
                .authenticationEntryPoint((swe, e) -> Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED)))
                .accessDeniedHandler((swe, e) -> Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN)))

                .and().authorizeExchange();

       return http.build();
   }
}



Beantwortet von –
dcg


Antwort geprüft von –
Clifford M. (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like