feat : ajout fonctionnalité login

This commit is contained in:
2025-12-01 18:09:42 +01:00
parent 6f9bbe47ab
commit 915f7a06f9
7 changed files with 62 additions and 63 deletions

View File

@@ -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>

View File

@@ -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";
} }
} }

View File

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

View File

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