Nach der Anmeldung mit Spring Security auf verschiedene Seiten umleiten

1. Übersicht

Eine häufige Anforderung für eine Webanwendung besteht darin, verschiedene Benutzertypen nach der Anmeldung auf verschiedene Seiten umzuleiten . Ein Beispiel hierfür wäre beispielsweise das Umleiten von Standardbenutzern auf eine Seite /homepage.html und von Administratoren auf eine Seite /console.html .

Dieser Artikel zeigt, wie Sie diesen Mechanismus mithilfe von Spring Security schnell und sicher implementieren können. Der Artikel baut auch auf dem Spring MVC-Tutorial auf, das sich mit dem Einrichten der für das Projekt erforderlichen MVC-Kernaufgaben befasst.

2. Die Spring Security-Konfiguration

Spring Security bietet eine Komponente, die direkt dafür verantwortlich ist, zu entscheiden, was nach einer erfolgreichen Authentifizierung zu tun ist - den AuthenticationSuccessHandler .

2.1. Basiseinstellung

Konfigurieren wir zunächst eine grundlegende @ Configuration- und @ Service- Klasse:

@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 } }

Der Teil dieser Konfiguration, auf den Sie sich konzentrieren sollten, ist die defaultSuccessUrl () -Methode. Nach einer erfolgreichen Anmeldung wird jeder Benutzer zu homepage.html weitergeleitet .

Darüber hinaus müssen wir Benutzer und ihre Rollen konfigurieren. In diesem Artikel implementieren wir einen einfachen UserDetailService mit zwei Benutzern, die jeweils eine einzelne Rolle haben. Weitere Informationen zu diesem Thema finden Sie in unserem Artikel Spring Security - Rollen und Berechtigungen.

@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)); } } 

Beachten Sie auch, dass in diesem einfachen Beispiel kein Kennwortcodierer verwendet wird. Daher wird den Kennwörtern das Präfix {noop} vorangestellt .

2.2. Hinzufügen des benutzerdefinierten Erfolgshandlers

Wir haben jetzt zwei Benutzer mit zwei unterschiedlichen Rollen: Benutzer und Administrator . Nach einer erfolgreichen Anmeldung werden beide zu hompeage.html umgeleitet . Schauen wir uns an, wie wir je nach Benutzerrolle eine andere Umleitung durchführen können.

Zunächst müssen wir einen benutzerdefinierten Erfolgshandler als Bean definieren:

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

Ersetzen Sie dann den Aufruf defaultSuccessUrl durch die Methode successHandler , die unseren benutzerdefinierten Erfolgshandler als Parameter akzeptiert:

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

2.3. XML-Konfiguration

Bevor wir uns die Implementierung unseres benutzerdefinierten Erfolgs-Handlers ansehen, schauen wir uns auch die entsprechende XML-Konfiguration an:

3. Der benutzerdefinierte Authentifizierungserfolgshandler

Neben der AuthenticationSuccessHandler- Schnittstelle bietet Spring auch einen sinnvollen Standard für diese Strategiekomponente - den AbstractAuthenticationTargetUrlRequestHandler und eine einfache Implementierung - den SimpleUrlAuthenticationSuccessHandler . In der Regel ermitteln diese Implementierungen die URL nach der Anmeldung und führen eine Umleitung zu dieser URL durch.

Der Mechanismus zum Ermitteln dieser Ziel-URL ist zwar etwas flexibel, ermöglicht jedoch keine programmgesteuerte Ermittlung. Daher werden wir die Schnittstelle implementieren und eine benutzerdefinierte Implementierung des Erfolgshandlers bereitstellen. Diese Implementierung bestimmt die URL, zu der der Benutzer nach der Anmeldung umgeleitet werden soll, basierend auf der Rolle des Benutzers.

Zunächst müssen wir die onAuthenticationSuccess- Methode überschreiben :

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); } 

Unsere angepasste Methode ruft zwei Hilfsmethoden auf:

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); } 

Wobei die folgende Methode die eigentliche Arbeit erledigt und den Benutzer der Ziel-URL zuordnet:

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(); } 

Beachten Sie, dass diese Methode die zugeordnete URL für die erste Rolle des Benutzers zurückgibt. Wenn ein Benutzer mehrere Rollen hat, entspricht die zugeordnete URL der ersten Rolle, die in der Berechtigungssammlung angegeben ist .

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

Die DetermineTargetUrl - das ist der Kern der Strategie - betrachtet einfach den Benutzertyp (von der Behörde festgelegt) und wählt die Ziel-URL basierend auf dieser Rolle aus .

Daher wird ein Administrator , der von der Berechtigung ROLE_ADMIN festgelegt wurde, nach der Anmeldung auf die Konsolenseite umgeleitet, während der von ROLE_USER festgelegte Standardbenutzer auf die Startseite umgeleitet wird.

4. Fazit

Wie immer ist der in diesem Artikel vorgestellte Code auf GitHub verfügbar. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.