1

Ich versuche, eine Spring Security in einer reaktiven Frühjahr Boot-Anwendung zu konfigurieren und enthielt das übergeordnete Projekt, das auf die neue Frühlings-Sicherheits Version setzt 5.0.0.RC1:ReactiveSecurityContextHolder kehrt nicht authentifizierte Benutzer

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>2.0.0.M6</version> 
</parent> 

Ich habe meine Spring WebSecurity so konfiguriert, dass sie einen benutzerdefinierten AuthenticationFilter verwendet, um meine Authentifizierungsinformationen sowie einen benutzerdefinierten AuthenticationManager mit meinen eigenen Providern abzurufen.

Config:

@EnableWebFluxSecurity 
@EnableReactiveMethodSecurity 
public class WebSecurityConfig { 

    private ServerAuthenticationEntryPoint entryPoint = new CustomServerAuthenticationEntryPoint(); 

    @Bean 
    SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception { 
     return http 
      // we rely on method security 
      .authorizeExchange() 
       .anyExchange().permitAll() 
      .and() 
       .logout().disable() 
       .authenticationManager(authenticationManager()) 
       //Override BasicAuthenticationEntryPoint 
       .exceptionHandling().serverAuthenticationEntryPoint(this.entryPoint) 
      .and() 
       .addFilterAt(upmAuthenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION) 
      .build(); 
    } 


    private ReactiveAuthenticationManager authenticationManager() { 
     return new CustomReactiveAuthenticationManager() 
      .authenticationProvider(new CustomAuthenticationProvider()); 
    } 

    private AuthenticationWebFilter upmAuthenticationWebFilter() { 
     try { 
      AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(authenticationManager()); 
      authenticationFilter.setServerAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); 
      authenticationFilter.setAuthenticationConverter(new CustomAuthenticationConverter();); 

      return authenticationFilter; 
     } catch (Exception e) { 
      throw new BeanInitializationException("Could not initialize AuthenticationWebFilter.", e); 
     } 
    } 
} 

ReactiveAuthenticationManager:

public class CustomReactiveAuthenticationManager implements ReactiveAuthenticationManager { 

    private List<AuthenticationProvider> authenticationProvider = new ArrayList<>(); 

    public CustomReactiveAuthenticationManager customAuthenticationProvider(
     final AuthenticationProvider customAuthenticationProvider) { 
     this.authenticationProvider.add(customAuthenticationProvider); 
     return this; 
    } 

    @Override 
    public Mono<Authentication> authenticate(final Authentication authentication) { 
     Class<? extends Authentication> toTest = authentication.getClass(); 
     for(AuthenticationProvider provider: authenticationProvider) { 
      if (provider.supports(toTest)) { 
       try { 

        //The provider returns a full authenticated Authentication object. 
        //With authentication.setAuthenticated(true); 
        return Mono.just(provider.authenticate(authentication)); 
       } catch (Exception e) { 
        return Mono.error(new BadCredentialsException("Invalid Credentials")); 
       } 
      } 
     } 
     return Mono.error(new ProviderNotFoundException("Unsupported Credentials")); 
    } 
} 

Wenn ich nun einen Anruf auf einem Endpoint durchführen, die einen authentifizierten Benutzer erfordert. Wie:

public interface HelloService { 
    /** 
    * This method returns just 'Hello, world!'. 
    * 
    * @return Return 'Hello, world!'. 
    */ 
    @PreAuthorize("isAuthenticated()") 
    Mono<String> getHelloWorld(); 
} 

Ich bekomme immer eine 401 AccessDenied-Ausnahme.

Nachdem es an der PrePostAdviceReactiveMethodInterceptor Linie 75

Debuggen in
auth -> this.preInvocationAdvice.before(auth, invocation, preAttr) 

Ich sah, dass das übergebene Objekt Authentication ein anonymer Benutzer ist.

Jetzt meine Frage: Habe ich vergessen, etwas für die Verwendung mit dem ReactiveSecurityContext zu konfigurieren?

Letzte Woche habe ich immer noch die vorherige MilestoneRelease M5 verwendet, wo das reaktive Spring-Security-Paket noch extra gefunden wurde, unter Spring-Security-Reactive. In diesem Fall wurde das Authentifizierungsobjekt abgerufen und meine Anfrage konnte abgeschlossen werden.

Antwort

0

Wenn jemand an dem Problem interessiert ist.

Ich habe keine serverSecurityContextRepository im AuthenticationWebFilter festgelegt.

So Einstellung löste das Problem.

private AuthenticationWebFilter upmAuthenticationWebFilter() { 
    try { 
     AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(authenticationManager()); 
     authenticationFilter.setServerAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); 
     authenticationFilter.setAuthenticationConverter(new CustomAuthenticationConverter();); 

     //Setting the Context Repo helped 
     authenticationFilter.setServerSecurityContextRepository(new WebSessionServerSecurityContextRepository()); 

     return authenticationFilter; 
    } catch (Exception e) { 
     throw new BeanInitializationException("Could not initialize AuthenticationWebFilter.", e); 
    } 
} 
0

als Repository Einstellung nicht für mich arbeiten, habe ich nur noch die Haupt meiner REST-Funktion:

@GetMapping("/select") 
public Mono<String> select(java.security.Principal principal) { 
    log.debug("Authorities: {}", ((Authentication) principal).getAuthorities()); 
} 
Verwandte Themen