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>