4 votes

Page de connexion propre dans spring security 6. nouvelle implémentation

J'essaie de migrer mon projet vers Spring Security 6. Je ne peux plus utiliser 'extends WebSecurityConfigurerAdapter'. Dans ce cas, je ne sais pas comment je peux reconstruire mon code pour utiliser ma propre page de connexion. Il y a un ancien code :

package main.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
            .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN", "EMPLOYEE")
            .and()
            .withUser("employee").password(passwordEncoder().encode("employee")).roles("EMPLOYEE")
            .and()
            .withUser("client").password(passwordEncoder().encode("client")).roles("CLIENT");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/login")
                .permitAll()
            .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/checkUserAccount")
                .defaultSuccessUrl("/")
                .permitAll()
            .and()
                .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .permitAll();
    }

}

J'ai donc vu dans la documentation que je pouvais la remplacer par la méthode SecurityFilterChain. Mon code, après un long moment, ressemble à ceci

package main.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    public UserDetailsService users() {
        UserDetails admin = User.withUsername("admin")
            .password(passwordEncoder().encode("admin"))
            .roles("ADMIN", "EMPLOYEE").build();
        UserDetails employee = User.withUsername("employee")
            .password(passwordEncoder().encode("employee"))
            .roles("EMPLOYEE").build();
        UserDetails client = User.withUsername("client")
            .password(passwordEncoder().encode("client"))
            .roles("CLIENT").build();
        return new InMemoryUserDetailsManager(admin, employee, client);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests() 
        .requestMatchers("/", "/login")
        .permitAll()
        .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/checkUserAccount")
            .defaultSuccessUrl("/")
            .permitAll()
        .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/")
            .invalidateHttpSession(true)
            .permitAll();
        return http.build();
    }

}

mais malheureusement, il est rejeté :

> 
SEVERE: Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'filterChain' defined in main.config.SecurityConfiguration: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'filterChain' threw exception with message: No bean named 'A Bean named mvcHandlerMappingIntrospector of type org.springframework.web.servlet.handler.HandlerMappingIntrospector is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.' available

Je suis un débutant, merci de votre aide.

Editer :

Il existe également SecurityInitializer :

 package main.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

Et voici mon login.html :

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

<link rel="stylesheet" href="http://use.fontawesome.com/releases/v5.3.1/css/all.css">
<link rel="stylesheet" type="text/css" href="resources/css/login.css">
</head>
<body>
    <div class="container">
        <div class="d-flex justify-content-center h-100">
            <div class="card">
                <div class="card-header">
                    <h2>Sign In</h2>
                </div>
                <div class="card-body">
                    <form action="#" th:action="@{/checkUserAccount}" method="post">
                        <div th:if="${param.error}" class="alert alert-login">
                            Invalid username and password.
                        </div>

                        <div class="input-group form-group">
                            <div class="input-group-prepend">
                                <span class="input-group-text"><i class="fas fa-user"></i></span>
                            </div>
                            <input type="text" class="form-control" name="username" placeholder="Login">
                        </div>
                        <div class="input-group form-group">
                            <div class="input-group-prepend">
                                <span class="input-group-text"><i class="fas fa-key"></i></span>
                            </div>
                            <input type="password" class="form-control" name="password" placeholder="Password">
                        </div>
                        <div class="form-group">
                            <input type="submit" value="Login" class="btn login-button">
                            <a th:href="@{/}" class="btn btn-warning float-right">Back</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Edit2 : Sans SecurityFilterChain cela fonctionne mais manifestement cela ne me dirige pas vers mon propre login. Quand j'exécute cela maintenant, je vois ceci :

Erreur lors de la création d'un bean avec un nom 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration' : Dépendance non satisfaite exprimée par la méthode 'setFilterChains' parameter 0 : Error creating bean with name 'filterChain' defined in main.config.SecurityConfiguration : Échec de l'instanciation [org.springframework.security.web.SecurityFilterChain] : La méthode d'usine 'filterChain' a levé une exception avec le message : Aucun bean nommé 'A Bean nommé mvcHandlerMappingIntrospector de type org.springframework.web.servlet.handler.HandlerMappingIntrospector est nécessaire pour utiliser MvcRequestMatcher. Veuillez vous assurer que Spring Security & Spring MVC sont configurés dans un ApplicationContext partagé" disponible

J'ai également ces dépendances :

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.0.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>6.0.1</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.0.3</version>
</dependency>

0voto

hev1 Points 6033

Au lieu d'utiliser AuthenticationManagerBuilder , créer un UserDetailsService haricot.

@Bean
public UserDetailsService users() {
    UserDetails admin = User.withUsername("admin")
        .password(passwordEncoder().encode("admin"))
        .roles("ADMIN", "EMPLOYEE").build();
    UserDetails employee = User.withUsername("employee")
        .password(passwordEncoder().encode("employee"))
        .roles("EMPLOYEE").build();
    UserDetails client = User.withUsername("client")
        .password(passwordEncoder().encode("client"))
        .roles("CLIENT").build();
    return new InMemoryUserDetailsManager(admin, employee, client);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X