Omleiden naar verschillende pagina's na inloggen met Spring Security

1. Overzicht

Een veel voorkomende vereiste voor een webapplicatie is om leiden verschillende soorten gebruikers door naar verschillende pagina's na inloggen. Een voorbeeld hiervan is het omleiden van standaardgebruikers naar een /homepage.html pagina en admin-gebruikers naar een /console.html pagina bijvoorbeeld.

Dit artikel laat zien hoe u dit mechanisme snel en veilig implementeert met Spring Security. Het artikel bouwt ook voort op de Spring MVC-zelfstudie die zich bezighoudt met het opzetten van de belangrijkste MVC-dingen die nodig zijn voor het project.

2. De Spring-beveiligingsconfiguratie

Spring Security biedt een component die de directe verantwoordelijkheid heeft om te beslissen wat te doen na een succesvolle authenticatie - het AuthenticationSuccessHandler.

2.1. Basisconfiguratie

Laten we eerst een basic configureren @Configuratie en @Onderhoud klasse:

@Configuration @EnableWebSecurity openbare klasse SecSecurityConfig breidt WebSecurityConfigurerAdapter uit {@Override protected void configure (laatste HttpSecurity http) gooit Uitzondering {http .authorizeRequests () // ... endpoints .formLogin () .loginPage ("/ login.html"). ("/ login") .defaultSuccessUrl ("/ homepage.html", true) // ... andere configuratie}}

Het deel van deze configuratie waarop u zich moet concentreren, is het defaultSuccessUrl () methode. Na een succesvolle login wordt elke gebruiker doorgestuurd naar homepage.html.

Verder moeten we gebruikers en hun rollen configureren. Voor de toepassing van dit artikel zullen we een eenvoudig UserDetailService met twee gebruikers die elk één enkele rol hebben. Lees ons artikel Spring Security - Roles and Privileges voor meer informatie over dit onderwerp.

@Service openbare klasse MyUserDetailsService implementeert UserDetailsService {privékaartrollen = nieuwe HashMap (); @PostConstruct public void init () {rollen.put ("admin2", nieuwe gebruiker ("admin", "{noop} admin1", getAuthority ("ROLE_ADMIN"))); rollen.put ("gebruiker2", nieuwe gebruiker ("gebruiker", "{noop} gebruiker1", getAuthority ("ROLE_USER"))); } @Override openbare UserDetails loadUserByUsername (String gebruikersnaam) {return rolls.get (gebruikersnaam); } privélijst getAuthority (String-rol) {return Collections.singletonList (nieuwe SimpleGrantedAuthority (rol)); }} 

Merk ook op dat we in dit eenvoudige voorbeeld geen wachtwoord-encoder gebruiken, daarom worden de wachtwoorden voorafgegaan door {noop}.

2.2. De aangepaste handler voor succes toevoegen

We hebben nu twee gebruikers met de twee verschillende rollen: gebruiker en beheerder. Na een succesvolle login worden beide doorgestuurd naar hompeage.html. Laten we eens kijken hoe we een andere omleiding kunnen hebben op basis van de rol van de gebruiker.

Eerst moeten we een aangepaste handler voor succes definiëren als een boon:

@Bean openbare AuthenticationSuccessHandler myAuthenticationSuccessHandler () {retourneer nieuwe MySimpleUrlAuthenticationSuccessHandler (); } 

En vervang dan het defaultSuccessUrl bellen met de successHandler methode, die onze aangepaste handler voor succes accepteert als parameter:

@Override protected void configure (final HttpSecurity http) gooit uitzondering {http .authorizeRequests () // endpoints .formLogin () .loginPage ("/ login.html") .loginProcessingUrl ("/ login") .successHandler (myAuthenticationSuccessHandler ()) // andere configuratie} 

2.3. XML-configuratie

Voordat we kijken naar de implementatie van onze aangepaste handler voor succes, laten we ook kijken naar de equivalente XML-configuratie:

3. De aangepaste handler voor geslaagde authenticatie

naast de AuthenticationSuccessHandler interface, biedt Spring ook een verstandige standaard voor deze strategiecomponent - de AbstractAuthenticationTargetUrlRequestHandler en een eenvoudige implementatie - de SimpleUrlAuthenticationSuccessHandler. Meestal bepalen deze implementaties de URL na het inloggen en voeren ze een omleiding naar die URL uit.

Hoewel enigszins flexibel, staat het mechanisme om deze doel-URL te bepalen niet toe dat de bepaling programmatisch wordt gedaan - dus gaan we de interface implementeren en een aangepaste implementatie van de succes-handler bieden. Deze implementatie gaat de URL bepalen waarnaar de gebruiker moet worden omgeleid na het inloggen op basis van de rol van de gebruiker.

Allereerst moeten we de onAuthenticationSuccess methode:

openbare klasse MySimpleUrlAuthenticationSuccessHandler implementeert AuthenticationSuccessHandler {protected Log logger = LogFactory.getLog (this.getClass ()); private RedirectStrategy redirectStrategy = nieuwe DefaultRedirectStrategy (); @Override public void onAuthenticationSuccess (HttpServletRequest-verzoek, HttpServletResponse-antwoord, authenticatieverificatie) gooit IOException {handle (verzoek, antwoord, authenticatie); clearAuthenticationAttributes (verzoek); } 

Onze aangepaste methode roept twee hulpmethoden op:

beschermde ongeldige handgreep (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Authenticatie-authenticatie) gooit IOException {String targetUrl = determinTargetUrl (authenticatie); if (response.isCommitted ()) {logger.debug ("Reactie is al vastgelegd. Kan niet omleiden naar" + targetUrl); terugkeren; } redirectStrategy.sendRedirect (verzoek, antwoord, targetUrl); } 

Waar de volgende methode het eigenlijke werk doet en de gebruiker toewijst aan de doel-URL:

protected String determinTargetUrl (laatste authenticatie authenticatie) {Map roleTargetUrlMap = nieuwe HashMap (); roleTargetUrlMap.put ("ROLE_USER", "/homepage.html"); roleTargetUrlMap.put ("ROLE_ADMIN", "/console.html"); definitieve incasso-autoriteiten = authentication.getAuthorities (); voor (laatste GrantedAuthority verleendAuthority: autoriteiten) {String autoriteitNaam = verleendAuthoriteit.getAuthority (); if (roleTargetUrlMap.containsKey (autoriteitNaam)) {return roleTargetUrlMap.get (autoriteitNaam); }} gooi nieuwe IllegalStateException (); } 

Merk op dat deze methode de toegewezen URL retourneert voor de eerste rol die de gebruiker heeft. Dus als een gebruiker meerdere rollen heeft, is de toegewezen URL de URL die overeenkomt met de eerste rol die in het autoriteiten verzameling.

beschermde ongeldige clearAuthenticationAttributes (verzoek HttpServletRequest) {HttpSession-sessie = request.getSession (false); if (session == null) {return; } session.removeAttribute (WebAttributes.AUTHENTICATION_EXCEPTION); }

De bepalenTargetUrl - dat is de kern van de strategie - kijkt gewoon naar het type gebruiker (bepaald door de autoriteit) en kiest de doel-URL op basis van deze rol.

Dus een admin gebruiker - bepaald door de ROLE_ADMIN autoriteit - wordt na het inloggen doorgestuurd naar de consolepagina, while de standaardgebruiker - zoals bepaald door ROLE_USER - wordt doorgestuurd naar de homepage.

4. Conclusie

Zoals altijd is de code die in dit artikel wordt gepresenteerd, beschikbaar op GitHub. Dit is een op Maven gebaseerd project, dus het zou gemakkelijk moeten kunnen worden geïmporteerd en uitgevoerd zoals het is.