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

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

1. Vue d'ensemble

Une exigence courante pour une application Web est deredirect different types of users to different pages after login. 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 vous expliquera comment mettre en œuvre rapidement et en toute sécurité ce mécanisme à l'aide de Spring Security. L'article s'appuie également sur lesSpring MVC tutorial qui traitent 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 - lesAuthenticationSuccessHandler.

Voyons comment nous pouvons configurer cela dans une classe@Configuration:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean("authenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // @formatter:off
        auth.inMemoryAuthentication()
            .withUser("user1").password("{noop}user1Pass").roles("USER")
            .and()
            .withUser("admin1").password("{noop}admin1Pass").roles("ADMIN");
        // @formatter:on
    }

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

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/anonymous*").anonymous()
            .antMatchers("/login*").permitAll()
            .anyRequest().authenticated()

            .and()
            .formLogin()
            .loginPage("/login.html")
            .loginProcessingUrl("/login")
            .successHandler(myAuthenticationSuccessHandler())
            // ...
    }
}

Les parties de cette configuration sur lesquelles se concentrer sont la définition de the custom authentication success handler bean and using the successHandler() method to add the bean to the security configuration.

Le reste de la configuration est assez standard: un simple élémenthttp qui sécurise tout et n'autorise qu'un accès non authentifié à/login*, et le fournisseur d'authentification en mémoire standard pour simplifier les choses.

Et la configuration xml équivalente:


    
    

    
    





    
        
            
            
        
    

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

Outre l'interfaceAuthenticationSuccessHandler, Spring fournit également une valeur par défaut raisonnable pour ce composant de stratégie - lesAbstractAuthenticationTargetUrlRequestHandler et une implémentation simple - lesSimpleUrlAuthenticationSuccessHandler. Généralement, ces implémentations déterminent l'URL après la connexion et effectuent une redirection vers cette URL.

Bien que quelque peu flexible, le mécanisme permettant de déterminer cette URL cible ne permet pas de déterminer par programme. Nous allons donc implémenter l'interface et fournir une implémentation personnalisée du gestionnaire de réussite. This implementation is going to determine the URL to redirect the user to after login based on the role of the user:

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

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

    protected String determineTargetUrl(Authentication authentication) {
        boolean isUser = false;
        boolean isAdmin = false;
        Collection authorities
         = authentication.getAuthorities();
        for (GrantedAuthority grantedAuthority : authorities) {
            if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
                isUser = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
                isAdmin = true;
                break;
            }
        }

        if (isUser) {
            return "/homepage.html";
        } else if (isAdmin) {
            return "/console.html";
        } else {
            throw new IllegalStateException();
        }
    }

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

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }
    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}

LedetermineTargetUrl - qui est au cœur de la stratégie - regarde simplement le type d'utilisateur (déterminé par l'autorité) etpicks the target URL based on this role.

Ainsi, unadmin user - déterminé par l'autoritéROLE_ADMIN - sera redirigé vers la page de la console après la connexion, tandis quethe standard user - tel que déterminé parROLE_USER - sera redirigé vers le page d'accueil.

4. Conclusion

Comme toujours, le code présenté dans cet article est disponibleover on Github. Ceci est un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.