Deux pages de connexion avec Spring Security

Deux pages de connexion avec Spring Security

1. introduction

Dans ce tutoriel, nous verrons comment nous pouvonsconfigure Spring Security to work with two different login pages en utilisant deux éléments Spring Securityhttp différents dans la configuration.

2. Configuration de 2 éléments Http

L'une des situations dans lesquelles nous pouvons avoir besoin de deux pages de connexion est lorsque nous avons une page pour les administrateurs d'une application et une page différente pour les utilisateurs normaux.

Nous allonsconfigure two http elements qui seront différenciés par le modèle d'URL associé à chacun:

  • /user * pour les pages qui auront besoin d'une authentification utilisateur normale pour être accédées

  • /admin * pour les pages qui seront accessibles par un administrateur

Chaque élémenthttp aura une page de connexion différente et une URL de traitement de connexion différente.

Afin de configurer deux élémentshttp différents, créons deux classes statiques annotées avec@Configuration qui étendent lesWebSecurityConfigurerAdapter.

Les deux seront placés dans une classe normale@Configuration:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    ...
}

Définissons lesWebSecurityConfigurerAdapter pour les utilisateurs“ADMIN”:

@Configuration
@Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
    public App1ConfigurationAdapter() {
        super();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/admin*")
          .authorizeRequests()
          .anyRequest()
          .hasRole("ADMIN")

          .and()
          .formLogin()
          .loginPage("/loginAdmin")
          .loginProcessingUrl("/admin_login")
          .failureUrl("/loginAdmin?error=loginError")
          .defaultSuccessUrl("/adminPage")

          .and()
          .logout()
          .logoutUrl("/admin_logout")
          .logoutSuccessUrl("/protectedLinks")
          .deleteCookies("JSESSIONID")

          .and()
          .exceptionHandling()
          .accessDeniedPage("/403")

          .and()
          .csrf().disable();
    }
}

Et maintenant, définissons lesWebSecurityConfigurerAdapter pour les utilisateurs normaux:

@Configuration
@Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    public App2ConfigurationAdapter() {
        super();
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/user*")
          .authorizeRequests()
          .anyRequest()
          .hasRole("USER")

          .and()
          .formLogin()
          .loginPage("/loginUser")
          .loginProcessingUrl("/user_login")
          .failureUrl("/loginUser?error=loginError")
          .defaultSuccessUrl("/userPage")

          .and()
          .logout()
          .logoutUrl("/user_logout")
          .logoutSuccessUrl("/protectedLinks")
          .deleteCookies("JSESSIONID")

          .and()
          .exceptionHandling()
          .accessDeniedPage("/403")

          .and()
          .csrf().disable();
    }
}

Notez qu'en plaçant l'annotation@Order sur chaque classe statique, nous spécifions l'ordre dans lequel les deux classes seront considérées en fonction du motif correspondant lorsqu'une URL est demandée.

Deux classes de configuration ne peuvent pas avoir le même ordre.

3. Pages de connexion personnalisées

Nous allons créer nos propres pages de connexion personnalisées pour chaque type d'utilisateur. Pour l'utilisateur administrateur, le formulaire de connexion aura une action“user_login”, comme défini dans la configuration:

User login page

User:
Password:

La page de connexion de l'administrateur est similaire, sauf que le formulaire aura une action de“admin_login” selon la configuration java.

4. Configuration de l'authentification

Nous devons maintenantconfigure authentication for our application. Examinons deux façons d’y parvenir: l’une en utilisant une source commune pour l’authentification des utilisateurs et l’autre en utilisant deux sources distinctes.

4.1. Utilisation d'une source d'authentification utilisateur commune

Si les deux pages de connexion partagent une source commune d'authentification des utilisateurs, vous pouvez créer un seul bean de typeUserDetailsService qui gérera l'authentification.

Illustrons ce scénario en utilisant unInMemoryUserDetailsManager qui définit deux utilisateurs - un avec un rôle de“USER” et un avec un rôle de“ADMIN”:

@Bean
public UserDetailsService userDetailsService() throws Exception {
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    manager.createUser(User
      .withUsername("user")
      .password(encoder().encode("userPass"))
      .roles("USER")
      .build());

    manager.createUser(User
      .withUsername("admin")
      .password(encoder().encode("adminPass"))
      .roles("ADMIN")
      .build());

    return manager;
}

@Bean
public static PasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
}

4.2. Utilisation de deux sources d'authentification utilisateur différentes

Si vous avez différentes sources pour l'authentification des utilisateurs - une pour les administrateurs et une pour les utilisateurs normaux - vous pouvez configurer unAuthenticationManagerBuilder à l'intérieur de chaque classe statique@Configuration. Prenons un exemple de gestionnaire d'authentification pour un utilisateur“ADMIN”:

@Configuration
@Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
          .withUser("admin")
          .password(encoder().encode("admin"))
          .roles("ADMIN");
    }
}

Dans ce cas, le beanUserDetailsService de la section précédente ne sera plus utilisé.

6. Conclusion

Dans ce rapide tutoriel, nous avons montré comment implémenter deux pages de connexion différentes dans la même application Spring Security.

Le code complet de cet article se trouve dans leGitHub project.

Lorsque vous exécutez l'application, vous pouvez accéder aux exemples ci-dessus sur l'URI de/protectedLinks.