feat : ajout fonctionnalité login
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -79,17 +79,13 @@
|
|||||||
<artifactId>spring-boot-starter-webmvc-test</artifactId>
|
<artifactId>spring-boot-starter-webmvc-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.validation</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>jakarta.validation-api</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package local.epul4a.fotosharing.controller;
|
|||||||
|
|
||||||
import local.epul4a.fotosharing.model.Utilisateur;
|
import local.epul4a.fotosharing.model.Utilisateur;
|
||||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
@@ -13,7 +14,9 @@ import jakarta.validation.Valid;
|
|||||||
@Controller
|
@Controller
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private final UtilisateurRepository utilisateurRepository;
|
private final UtilisateurRepository utilisateurRepository;
|
||||||
|
@Autowired
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
public AuthController(UtilisateurRepository utilisateurRepository, PasswordEncoder passwordEncoder) {
|
public AuthController(UtilisateurRepository utilisateurRepository, PasswordEncoder passwordEncoder) {
|
||||||
@@ -37,21 +40,19 @@ public class AuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
public String doRegister(@ModelAttribute("utilisateur") @Valid Utilisateur utilisateur,
|
public String register(@ModelAttribute Utilisateur utilisateur, Model model) {
|
||||||
BindingResult bindingResult, Model model) {
|
// Vérifier si l'email existe déjà
|
||||||
if (bindingResult.hasErrors()) {
|
|
||||||
return "register";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utilisateurRepository.findByEmail(utilisateur.getEmail()).isPresent()) {
|
if (utilisateurRepository.findByEmail(utilisateur.getEmail()).isPresent()) {
|
||||||
model.addAttribute("error", "Email déjà utilisé");
|
model.addAttribute("error", "Cet email est déjà utilisé");
|
||||||
return "register";
|
return "register";
|
||||||
}
|
}
|
||||||
|
|
||||||
// encoder le mot de passe puis sauvegarder
|
// CRUCIAL : Encoder le mot de passe avant de sauvegarder
|
||||||
utilisateur.setMotDePasse(passwordEncoder.encode(utilisateur.getMotDePasse()));
|
utilisateur.setMotDePasse(passwordEncoder.encode(utilisateur.getMotDePasse()));
|
||||||
utilisateur.setActif(true);
|
utilisateur.setActif(true);
|
||||||
|
|
||||||
utilisateurRepository.save(utilisateur);
|
utilisateurRepository.save(utilisateur);
|
||||||
|
|
||||||
return "redirect:/login?registered";
|
return "redirect:/login?registered";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,9 @@ package local.epul4a.fotosharing.security;
|
|||||||
|
|
||||||
import local.epul4a.fotosharing.model.Utilisateur;
|
import local.epul4a.fotosharing.model.Utilisateur;
|
||||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -9,16 +12,19 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
public class CustomUserDetailsService implements UserDetailsService {
|
public class CustomUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
private final UtilisateurRepository utilisateurRepository;
|
@Autowired
|
||||||
|
private UtilisateurRepository utilisateurRepository;
|
||||||
public CustomUserDetailsService(UtilisateurRepository utilisateurRepository) {
|
|
||||||
this.utilisateurRepository = utilisateurRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
|
||||||
Utilisateur u = utilisateurRepository.findByEmail(username)
|
Utilisateur utilisateur = utilisateurRepository.findByEmail(email)
|
||||||
.orElseThrow(() -> new UsernameNotFoundException("Utilisateur introuvable: " + username));
|
.orElseThrow(() -> new UsernameNotFoundException("Utilisateur non trouvé : " + email));
|
||||||
return new CustomUserDetails(u);
|
|
||||||
|
return User.builder()
|
||||||
|
.username(utilisateur.getEmail())
|
||||||
|
.password(utilisateur.getMotDePasse()) // Le hash BCrypt depuis la BD
|
||||||
|
.disabled(!utilisateur.isActif())
|
||||||
|
.authorities("USER")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,59 @@
|
|||||||
package local.epul4a.fotosharing.security;
|
package local.epul4a.fotosharing.security;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
import java.io.DataOutput;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
|
@EnableWebSecurity
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
|
||||||
private final CustomUserDetailsService customUserDetailsService;
|
@Autowired
|
||||||
|
private CustomUserDetailsService customUserDetailsService;
|
||||||
public SecurityConfig(CustomUserDetailsService customUserDetailsService) {
|
|
||||||
this.customUserDetailsService = customUserDetailsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
||||||
|
|
||||||
http
|
|
||||||
.authorizeHttpRequests(auth -> auth
|
|
||||||
.requestMatchers("/login", "/register", "/css/**", "/js/**").permitAll()
|
|
||||||
.anyRequest().authenticated()
|
|
||||||
)
|
|
||||||
.formLogin(form -> form
|
|
||||||
.loginPage("/login")
|
|
||||||
.defaultSuccessUrl("/", true)
|
|
||||||
.permitAll()
|
|
||||||
)
|
|
||||||
.logout(logout -> logout
|
|
||||||
.logoutSuccessUrl("/login?logout=true")
|
|
||||||
.permitAll()
|
|
||||||
)
|
|
||||||
.csrf(csrf -> csrf.disable());
|
|
||||||
|
|
||||||
return http.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService userDetailsService() {
|
|
||||||
// Spring Security 6.2 utilise ce bean automatiquement
|
|
||||||
return customUserDetailsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
|
||||||
// Spring Boot crée automatiquement un DaoAuthenticationProvider interne
|
|
||||||
return config.getAuthenticationManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||||
|
return config.getAuthenticationManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.userDetailsService(customUserDetailsService) // Utiliser directement le UserDetailsService
|
||||||
|
.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers("/register", "/login", "/css/**", "/js/**").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.formLogin(form -> form
|
||||||
|
.loginPage("/login")
|
||||||
|
.defaultSuccessUrl("/", true)
|
||||||
|
.failureUrl("/login?error=true")
|
||||||
|
.permitAll()
|
||||||
|
)
|
||||||
|
.logout(logout -> logout
|
||||||
|
.logoutSuccessUrl("/login?logout")
|
||||||
|
.permitAll()
|
||||||
|
);
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user