Gids voor de AuthenticationManagerResolver in Spring Security

1. Inleiding

In deze tutorial introduceren we AuthenticationManagerResolver en laat vervolgens zien hoe u het kunt gebruiken voor basis- en OAuth2-verificatiestromen.

2. Wat is het AuthenticationManager?

Simpel gezegd, de AuthenticationManager is de belangrijkste strategie-interface voor authenticatie.

Als het principe van de invoerauthenticatie geldig en geverifieerd is, AuthenticationManager # authenticate geeft een Authenticatie instantie met de geverifieerd vlag ingesteld op waar. Anders, als de principal niet geldig is, wordt een AuthenticationException. In het laatste geval keert het terug nul als het niet kan beslissen.

ProviderManager is de standaardimplementatie van AuthenticationManager. Het delegeert het authenticatieproces aan een lijst met AuthenticationProvider gevallen.

We kunnen globaal of lokaal opzetten AuthenticationManager als we verlengen WebSecurityConfigurerAdapter. Voor een local AuthenticationManager, zouden we kunnen negeren configureren (AuthenticationManagerBuilder).

AuthenticationManagerBuilder is een helperklasse die het opzetten van UserDetailService, AuthenticationProvider, en andere afhankelijkheden om een AuthenticationManager.

Voor een globaal AuthenticationManager, moeten we een AuthenticationManager als boon.

3. Waarom de AuthenticationManagerResolver?

AuthenticationManagerResolver laat Spring een AuthenticationManager per context. Het is een nieuwe functie toegevoegd aan Spring Security in versie 5.2.0:

openbare interface AuthenticationManagerResolver {AuthenticationManager-oplossing (C-context); }

AuthenticationManagerResolver # resolver kan een exemplaar retourneren van AuthenticationManager gebaseerd op een generieke context. Met andere woorden, we kunnen een klasse instellen als de context als we het AuthenticationManager volgens het.

Spring Security heeft het AuthenticationManagerResolver in de authenticatiestroom met HttpServletRequest en ServerWebExchange als de context.

4. Gebruiksscenario

Laten we eens kijken hoe we het kunnen gebruiken AuthenticationManagerResolver in praktijk.

Stel bijvoorbeeld een systeem met twee groepen gebruikers: medewerkers en klanten. Deze twee groepen hebben specifieke authenticatielogica en hebben aparte datastores. Bovendien mogen gebruikers in elk van deze groepen alleen hun gerelateerde URL's oproepen.

5. Hoe werkt AuthenticationManagerResolver Werk?

We kunnen gebruiken AuthenticationManagerResolver waar we een AuthenticationManager dynamisch, maar in deze tutorial zijn we geïnteresseerd in het gebruik ervan in ingebouwde authenticatiestromen.

Laten we eerst een AuthenticationManagerResolveren gebruik het vervolgens voor basis- en OAuth2-authenticaties.

5.1. Opzetten AuthenticationManagerResolver

Laten we beginnen met het maken van een klasse voor beveiligingsconfiguratie. We moeten verlengen WebSecurityConfigurerAdapter:

@Configuration openbare klasse CustomWebSecurityConfigurer breidt WebSecurityConfigurerAdapter {// ...} uit

Laten we vervolgens een methode toevoegen die de AuthenticationManager voor klanten:

AuthenticationManager customersAuthenticationManager () {retourneer authenticatie -> {if (isCustomer (authenticatie)) {retourneer nieuwe UsernamePasswordAuthenticationToken (/ * referenties * /); } throw nieuwe UsernameNotFoundException (/ * hoofdnaam * /); }; }

De AuthenticationManager voor medewerkers is logischerwijs hetzelfde, alleen wij vervangen isklant met isWerknemer:

openbare AuthenticationManager workersAuthenticationManager () {retourneer authenticatie -> {if (isEmployee (authenticatie)) {retourneer nieuwe UsernamePasswordAuthenticationToken (/ * referenties * /); } throw nieuwe UsernameNotFoundException (/ * hoofdnaam * /); }; }

Laten we tot slot een AuthenticationManagerResolver dat wordt opgelost volgens de URL van het verzoek:

AuthenticationManagerResolver resolver () {retouraanvraag -> {if (request.getPathInfo (). StartsWith ("/ employee")) {return workersAuthenticationManager (); } terugkeer customersAuthenticationManager (); }; }

5.2. Voor basisverificatie

We kunnen gebruiken AuthenticationFilter om het AuthenticationManager per aanvraag. AuthenticationFilter is toegevoegd aan Spring Security in versie 5.2.

Als we het toevoegen aan onze beveiligingsfilterketen, controleert het voor elk overeenkomend verzoek eerst of het een authenticatieobject kan extraheren of niet. Zo ja, dan wordt de AuthenticationManagerResolver voor een geschikt AuthenticationManager en zet de stroom voort.

Laten we eerst een methode toevoegen aan onze CustomWebSecurityConfigurer om een AuthenticationFilter:

privé AuthenticationFilter authenticationFilter () {AuthenticationFilter filter = nieuw AuthenticationFilter (resolver (), authenticationConverter ()); filter.setSuccessHandler ((verzoek, antwoord, auth) -> {}); retourfilter; }

De reden voor het instellen van de AuthenticationFilter # successHandler met een no-op SuccesHandler is om het standaardgedrag van omleiding na succesvolle authenticatie te voorkomen.

Vervolgens kunnen we dit filter toevoegen aan onze beveiligingsfilterketen door deze te overschrijven WebSecurityConfigurerAdapter # configureren (HttpSecurity) in onze CustomWebSecurityConfigurer:

@Override protected void configure (HttpSecurity http) genereert uitzondering {http.addFilterBefore (authenticationFilter (), BasicAuthenticationFilter.class); }

5.3. Voor OAuth2-verificatie

BearerTokenAuthenticationFilter is verantwoordelijk voor OAuth2-authenticatie. De BearerTokenAuthenticationFilter # doFilterInternal methode controleert op een BearerTokenAuthenticationToken in het verzoek, en als het beschikbaar is, lost het de juiste op AuthenticationManager om het token te authenticeren.

OAuth2ResourceServerConfigurer wordt gebruikt om op te zetten BearerTokenAuthenticationFilter.

Dus we kunnen het opzetten AuthenticationManagerResolver voor onze resource server in onze CustomWebSecurityConfigurer door te overschrijven WebSecurityConfigurerAdapter # configureren (HttpSecurity):

@Override protected void configure (HttpSecurity http) genereert uitzondering {http .oauth2ResourceServer () .authenticationManagerResolver (resolver ()); }

6. Los op AuthenticationManager in reactieve toepassingen

Voor een reactieve webapplicatie kunnen we nog steeds profiteren van het concept van oplossen AuthenticationManager volgens de context. Maar hier hebben we ReactiveAuthenticationManagerResolver in plaats daarvan:

@FunctionalInterface openbare interface ReactiveAuthenticationManagerResolver {Mono-oplossing (C-context); }

Het retourneert een Mono van ReactiveAuthenticationManager. ReactiveAuthenticationManager is het reactieve equivalent van AuthenticationManager, vandaar zijn authenticeren methode retourneert Mono.

6.1. Opzetten ReactiveAuthenticationManagerResolver

Laten we beginnen met het maken van een klasse voor beveiligingsconfiguratie:

@EnableWebFluxSecurity @EnableReactiveMethodSecurity openbare klasse CustomWebSecurityConfig {// ...}

Laten we vervolgens definiëren ReactiveAuthenticationManager voor klanten in deze klasse:

ReactiveAuthenticationManager customersAuthenticationManager () {return authentication -> customer (authentication) .switchIfEmpty (Mono.error (new UsernameNotFoundException (/ * principal name * /))) .map (b -> new UsernamePasswordAuthenticationToken (/ * credentials * /)); } 

En daarna zullen we definiëren ReactiveAuthenticationManager voor werknemers:

openbare ReactiveAuthenticationManager workersAuthenticationManager () {retourneer authenticatie -> medewerker (authenticatie) .switchIfEmpty (Mono.error (nieuwe UsernameNotFoundException (/ * hoofdnaam * /))) .map (b -> nieuwe UsernamePasswordAuthenticationToken (/ * referenties * /)); }

Ten slotte hebben we een ReactiveAuthenticationManagerResolver gebaseerd op ons scenario:

ReactiveAuthenticationManagerResolver resolver () {return exchange -> {if (match (exchange.getRequest (), "/ employee")) {return Mono.just (workersAuthenticationManager ()); } retourneer Mono.just (customersAuthenticationManager ()); }; }

6.2. Voor basisverificatie

In een reactieve webapplicatie kunnen we gebruiken AuthenticatieWebFilter voor authenticatie. Het verifieert het verzoek en vult de beveiligingscontext.

AuthenticatieWebFilter controleert eerst of het verzoek overeenkomt. Daarna, als er een authenticatieobject in het verzoek zit, wordt het geschikt ReactiveAuthenticationManager voor het verzoek van ReactiveAuthenticationManagerResolver en zet de authenticatiestroom voort.

Daarom kunnen we onze op maat gemaakte AuthenticatieWebFilter in onze beveiligingsconfiguratie:

@Bean public SecurityWebFilterChain securityWebFilterChain (ServerHttpSecurity http) {return http .authorizeExchange () .pathMatchers ("/ **") .authenticated () .and () .httpBasic () .disable () .addFilterAfter (nieuwe AuthenticationWebFilter (resolver () ), SecurityWebFiltersOrder.REACTOR_CONTEXT) .build (); }

Ten eerste schakelen we uit ServerHttpSecurity # httpBasic om de normale authenticatiestroom te voorkomen, vervang het dan handmatig door een AuthenticatieWebFilter, door onze aangepaste resolver door te geven.

6.3. Voor OAuth2-verificatie

We kunnen het ReactiveAuthenticationManagerResolver met ServerHttpSecurity # oauth2ResourceServer. ServerHttpSecurity # build voegt een instantie toe van AuthenticatieWebFilter met onze resolver naar de keten van beveiligingsfilters.

Dus laten we onze AuthenticationManagerResolver voor OAuth2-verificatiefilter in onze beveiligingsconfiguratie:

@Bean public SecurityWebFilterChain securityWebFilterChain (ServerHttpSecurity http) {return http // ... .and () .oauth2ResourceServer () .authenticationManagerResolver (resolver ()) .and () // ...; }

7. Conclusie

In dit artikel hebben we gebruikt AuthenticationManagerResolver voor basis- en OAuth2-authenticaties binnen een eenvoudig scenario.

En we hebben ook het gebruik van ReactiveAuthenticationManagerResolver in reactieve Spring-webapplicaties voor zowel basis- als OAuth2-authenticaties.

Zoals altijd is de broncode beschikbaar op GitHub. Ons reactieve voorbeeld is ook beschikbaar op GitHub.