Reindirizza a pagine diverse dopo l'accesso con Spring Security

1. Panoramica

Un requisito comune per un'applicazione Web è reindirizzare diversi tipi di utenti a pagine diverse dopo il login . Un esempio potrebbe essere il reindirizzamento degli utenti standard a una pagina /homepage.html e gli utenti amministratori a una pagina /console.html, ad esempio.

Questo articolo mostrerà come implementare in modo rapido e sicuro questo meccanismo utilizzando Spring Security. L'articolo si basa anche sul tutorial Spring MVC che si occupa della configurazione del materiale MVC di base necessario per il progetto.

2. La configurazione Spring Security

Spring Security fornisce un componente che ha la responsabilità diretta di decidere cosa fare dopo un'autenticazione riuscita: AuthenticationSuccessHandler .

2.1. Configurazione di base

Configuriamo prima una classe @Configuration e @Service di base :

@Configuration @EnableWebSecurity public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // ... endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .defaultSuccessUrl("/homepage.html", true) // ... other configuration } }

La parte di questa configurazione su cui concentrarsi è il metodo defaultSuccessUrl () . Dopo un accesso riuscito, qualsiasi utente verrà reindirizzato a homepage.html .

Inoltre, dobbiamo configurare gli utenti e i loro ruoli. Ai fini di questo articolo, implementeremo un semplice UserDetailService con due utenti, ciascuno con un unico ruolo. Per ulteriori informazioni su questo argomento, leggi il nostro articolo Spring Security - Roles and Privileges.

@Service public class MyUserDetailsService implements UserDetailsService { private Map roles = new HashMap(); @PostConstruct public void init() { roles.put("admin2", new User("admin", "{noop}admin1", getAuthority("ROLE_ADMIN"))); roles.put("user2", new User("user", "{noop}user1", getAuthority("ROLE_USER"))); } @Override public UserDetails loadUserByUsername(String username) { return roles.get(username); } private List getAuthority(String role) { return Collections.singletonList(new SimpleGrantedAuthority(role)); } } 

Si noti inoltre che in questo semplice esempio, non useremo un codificatore di password, quindi le password hanno il prefisso {noop} .

2.2. Aggiunta del gestore del successo personalizzato

Ora abbiamo due utenti con due ruoli diversi: utente e amministratore . Dopo un accesso riuscito, entrambi verranno reindirizzati a hompeage.html . Diamo un'occhiata a come possiamo avere un reindirizzamento diverso in base al ruolo dell'utente.

Innanzitutto, dobbiamo definire un gestore di successo personalizzato come un bean:

@Bean public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){ return new MySimpleUrlAuthenticationSuccessHandler(); } 

Quindi sostituire la chiamata defaultSuccessUrl con il metodo successHandler , che accetta il nostro gestore di successo personalizzato come parametro:

@Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .successHandler(myAuthenticationSuccessHandler()) // other configuration } 

2.3. Configurazione XML

Prima di esaminare l'implementazione del nostro gestore di successo personalizzato, diamo un'occhiata anche alla configurazione XML equivalente:

3. Il gestore del successo dell'autenticazione personalizzata

Oltre all'interfaccia AuthenticationSuccessHandler , Spring fornisce anche un valore predefinito ragionevole per questo componente della strategia - AbstractAuthenticationTargetUrlRequestHandler e una semplice implementazione - SimpleUrlAuthenticationSuccessHandler . In genere, queste implementazioni determineranno l'URL dopo l'accesso ed eseguiranno un reindirizzamento a tale URL.

Anche se alquanto flessibile, il meccanismo per determinare questo URL di destinazione non consente di eseguire la determinazione a livello di codice, quindi implementeremo l'interfaccia e forniremo un'implementazione personalizzata del gestore di successo. Questa implementazione determinerà l'URL a cui reindirizzare l'utente dopo l'accesso in base al ruolo dell'utente.

Prima di tutto, dobbiamo sovrascrivere il metodo onAuthenticationSuccess :

public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { protected Log logger = LogFactory.getLog(this.getClass()); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { handle(request, response, authentication); clearAuthenticationAttributes(request); } 

Il nostro metodo personalizzato chiama due metodi di supporto:

protected void handle( HttpServletRequest request, HttpServletResponse response, Authentication authentication ) throws IOException { String targetUrl = determineTargetUrl(authentication); if (response.isCommitted()) { logger.debug( "Response has already been committed. Unable to redirect to " + targetUrl); return; } redirectStrategy.sendRedirect(request, response, targetUrl); } 

Dove il seguente metodo fa il lavoro effettivo e mappa l'utente all'URL di destinazione:

protected String determineTargetUrl(final Authentication authentication) { Map roleTargetUrlMap = new HashMap(); roleTargetUrlMap.put("ROLE_USER", "/homepage.html"); roleTargetUrlMap.put("ROLE_ADMIN", "/console.html"); final Collection authorities = authentication.getAuthorities(); for (final GrantedAuthority grantedAuthority : authorities) { String authorityName = grantedAuthority.getAuthority(); if(roleTargetUrlMap.containsKey(authorityName)) { return roleTargetUrlMap.get(authorityName); } } throw new IllegalStateException(); } 

Tieni presente che questo metodo restituirà l'URL mappato per il primo ruolo che ha l'utente. Quindi, se un utente ha più ruoli, l'URL mappato sarà quello che corrisponde al primo ruolo fornito nella raccolta delle autorizzazioni .

protected void clearAuthenticationAttributes(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); }

Il determineTargetUrl - che è il cuore della strategia - semplicemente guarda il tipo di utente (determinato dall'autorità) e raccoglie l'URL di destinazione in base a questo ruolo .

Quindi, un utente amministratore , determinato dall'autorità ROLE_ADMIN , verrà reindirizzato alla pagina della console dopo l'accesso, mentre l'utente standard , come determinato da ROLE_USER , verrà reindirizzato alla home page.

4. Conclusione

Come sempre, il codice presentato in questo articolo è disponibile su GitHub. Questo è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.