Redirection vers différentes pages après la connexion avec Spring Security

1. Vue d'ensemble

Une exigence courante pour une application Web est de rediriger différents types d'utilisateurs vers différentes pages après la connexion . Un exemple de ceci serait de rediriger les utilisateurs standard vers une page /homepage.html et les utilisateurs administrateurs vers une page /console.html par exemple.

Cet article montre comment implémenter rapidement et en toute sécurité ce mécanisme à l'aide de Spring Security. L'article s'appuie également sur le didacticiel Spring MVC qui traite de la configuration des éléments MVC de base nécessaires au projet.

2. La configuration de sécurité Spring

Spring Security fournit un composant qui a la responsabilité directe de décider quoi faire après une authentification réussie - le AuthenticationSuccessHandler .

2.1. Configuration de base

Commençons par configurer une classe @Configuration et @Service de 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 partie de cette configuration sur laquelle se concentrer est la méthode defaultSuccessUrl () . Après une connexion réussie, tout utilisateur sera redirigé vers homepage.html .

De plus, nous devons configurer les utilisateurs et leurs rôles. Pour les besoins de cet article, nous allons implémenter un UserDetailService simple avec deux utilisateurs, chacun ayant un seul rôle. Pour en savoir plus sur ce sujet, lisez notre article 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)); } } 

Notez également que dans cet exemple simple, nous n'utiliserons pas d'encodeur de mot de passe, donc les mots de passe sont préfixés par {noop} .

2.2. Ajout du gestionnaire de succès personnalisé

Nous avons maintenant deux utilisateurs avec les deux rôles différents: utilisateur et administrateur . Après une connexion réussie, les deux seront redirigés vers hompeage.html . Voyons comment nous pouvons avoir une redirection différente en fonction du rôle de l'utilisateur.

Tout d'abord, nous devons définir un gestionnaire de succès personnalisé en tant que bean:

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

Et puis remplacez l' appel defaultSuccessUrl par la méthode successHandler , qui accepte notre gestionnaire de succès personnalisé en tant que paramètre:

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

2.3. Configuration XML

Avant d'examiner l'implémentation de notre gestionnaire de succès personnalisé, examinons également la configuration XML équivalente:

3. Le gestionnaire de réussite d'authentification personnalisée

Outre l' interface AuthenticationSuccessHandler , Spring fournit également une valeur par défaut raisonnable pour ce composant de stratégie - le AbstractAuthenticationTargetUrlRequestHandler et une implémentation simple - le SimpleUrlAuthenticationSuccessHandler . En règle générale, ces implémentations détermineront l'URL après la connexion et effectueront une redirection vers cette URL.

Bien que quelque peu flexible, le mécanisme pour déterminer cette URL cible ne permet pas que la détermination soit effectuée par programme - nous allons donc implémenter l'interface et fournir une implémentation personnalisée du gestionnaire de réussite. Cette implémentation va déterminer l'URL vers laquelle rediriger l'utilisateur après la connexion en fonction du rôle de l'utilisateur.

Tout d'abord, nous devons remplacer la méthode 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); } 

Notre méthode personnalisée appelle deux méthodes d'assistance:

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

Où la méthode suivante effectue le travail réel et mappe l'utilisateur à l'URL cible:

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

Notez que cette méthode renverra l'URL mappée pour le premier rôle de l'utilisateur. Ainsi, si un utilisateur a plusieurs rôles, l'URL mappée sera celle qui correspond au premier rôle donné dans la collection d' autorités .

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

La determineTargetUrl - qui est au cœur de la stratégie - regarde simplement le type d'utilisateur (déterminé par l'autorité) et choisit l'URL cible en fonction de ce rôle .

Ainsi, un utilisateur administrateur - déterminé par l' autorité ROLE_ADMIN - sera redirigé vers la page de la console après la connexion, tandis que l'utilisateur standard - tel que déterminé par ROLE_USER - sera redirigé vers la page d'accueil.

4. Conclusion

Comme toujours, le code présenté dans cet article est disponible à l'adresse over sur GitHub. Il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.