Bonjour,
Confinement oblige, je retravaille sur un projet maison qui me sert de base pour approfondir mes connaissances autour d'Angular et de Spring.
J'avais un ancien projet avec une configuration xml.

La configuration xml pour spring security était la suivante:
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- Activation des annotations @PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize sur chaque bean de 
	Spring -->
	<security:global-method-security pre-post-annotations="enabled" />
 
    <!-- On indique que pour "/rest/authentication", il n'y a pas de sécurité (tout le monde peut appeler pour 
    s'authentifier). -->
    <security:http pattern="/rest/authentication" security="none"/>
 
	<!-- On indique le point d'entrée lors d'un appel à tous les services REST (sauf celui déclaré juste 
	avant sur lequel on ne veut pas de sécurité). "stateless" indique qu'on ne veut pas de session 
	créée pour la sécurité vu que l'on utilise des token pour chaque requête. -->
    <security:http pattern="/rest/**" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless">
        <!-- Nous n'avons pas besoin de protection csrf car le token est immunisé à ca. -->
        <security:csrf disabled="true"/>
        <!-- On indique que l'on utilise un filtre customisé référencé par "jwtAuthenticationFilter" (défini 
        plus bas). Il sera placé avant le filtre pour le formulaire de login dans la chaine des filtres 
        prédéfinis dans Spring. -->
        <security:custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter"/>
    </security:http>
 
    <!-- On indique où se trouve notre filtre qui sera géré comme un bean par Spring. -->
    <bean id="jwtAuthenticationFilter" class="com.testAngularRestToken.filter.JwtAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationSuccessHandler" ref="jwtAuthenticationSuccessHandler" />
    </bean>
 
	<!-- On défini le "authenticationManager" qui va s'appuyer sur notre classe "JwtAuthenticationProvider". -->
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="jwtAuthenticationProvider" />
    </security:authentication-manager>

J'ai commencé la conversion en classe de configuration java qui n'est pas finie mais je ne sais pas si c'est correct:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
@Configuration
@EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
	@Autowired
    private JwtAuthenticationProvider jwtAuthProvider;
 
	// Configure
	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		httpSecurity
                // "stateless" indique qu'on ne veut pas de session créée pour la sécurité vu que l'on utilise 
		// des jetons JWT pour les requête.
		.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
		.and()
		// Nous n'avons pas besoin de protection csrf car le token qu'on utilise est immunisé à ca
  		.csrf().disable()
		 // Filtre personnalisé pour la vérification du token JWT
		.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
		// Configuration des accès selon la requête
		.authorizeRequests()
		// On autorise tout le monde pour des requêtes sur ces URLs
		.antMatchers("/rest/authentication").permitAll()
		// Pour toutes les autres requêtes sur les autres URLs on doit être authentifié
		.anyRequest()
		.authenticated()
		.and()
		// Permet d'activer l'authentification par HTTP basic. Utile dans mon cas?
		// Whenever an HTTP request is sent to the application Spring Security now checks if the header 
		// contains Authorization: Basic <credentials>.
		.httpBasic();
	}
 
	// Configure un authentication provider spécifique implémenté pour notre jeton JWT pour le 
	// authentication manager.
	@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(jwtAuthProvider);
    }
 
	// On définit le bean géré par Spring pour le filtrage des requêtes (vérification du jeton JWT).
	@Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter()
            throws Exception {
		JwtAuthenticationFilter lJwtAuthenticationFilter = new JwtAuthenticationFilter();
		lJwtAuthenticationFilter.setAuthenticationManager(authenticationManager());
		lJwtAuthenticationFilter.setAuthenticationSuccessHandler(new JwtAuthenticationSuccessHandler());
        return lJwtAuthenticationFilter;
    }
 
	// On défini le authenticationManager qui va s'appuyer sur notre classe "JwtAuthenticationProvider" 
	// pour la vérification du jeton JWT et la récupération des UserDetails (cf. méthode
	// configure(AuthenticationManagerBuilder auth) surchargée plus haut).
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
    	return super.authenticationManagerBean();
    }
 
	// On définit le password encoder à utiliser pour les mots de passe.
	// Cela va donc activer l'encodage et la vérification des mots de passe automatiquement par Spring 
	// Security en utilisant cet encoder.
	@Bean
	public PasswordEncoder passwordEncoder() {
		// Ici utilisation de BCrypt avec le facteur de travail 10 (valeur par défaut de Spring Security).
		// Utilisation d'un SecureRandom comme générateur de sel (donne un nombre aléatoire 
		// cryptographiquement fort).
		int lStrength = 10;
		return new BCryptPasswordEncoder(lStrength, new SecureRandom()); 
 
		// INFO: On peut aussi utiliser d'autres encoder
 
//		String pepper = "pepper"; // secret key used by password encoding
//		int iterations = 200000;  // number of hash iteration
//		int hashWidth = 256;      // hash width in bits
//		return new Pbkdf2PasswordEncoder(pepper, iterations, hashWidth);
 
//		int cpuCost = (int) Math.pow(2, 14); // factor to increase CPU costs
//		int memoryCost = 8;      // increases memory usage
//		int parallelization = 1; // currently not supported by Spring Security
//		int keyLength = 32;      // key length in bytes
//		int saltLength = 64;     // salt length in bytes
//		
//		return new SCryptPasswordEncoder(cpuCost, memoryCost, parallelization, keyLength, saltLength);
	}
 
	@Bean
	public AuthenticationProvider daoAuthenticationProvider() {
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
	    // Ajoute le password encoder définit au dessus au DaoAuthenticationProvider de Spring Security.
		provider.setPasswordEncoder(passwordEncoder());
	    // Définit le service servant au changement de mot de passe.
		provider.setUserDetailsPasswordService(this.databaseUserDetailPasswordService);
	    // Définit le service de récupération des données utilisateur pour l'authentification.
		provider.setUserDetailsService(this.databaseUserDetailsService);
	    return provider;
	}
}
En gros, voici la sécurité que je souhaite avoir:
- A la création d'un compte, le mot de passe utilisateur est hashé avec BCrypt (gestion du sel automatique de ce que j'ai compris)
- Quand l'utilisateur s'est authentifié, il y a un jeton JWT qui sera mis dans les header des requêtes et donc vérifié par le filtre côté back
- JwtAuthenticationFilter se charge d'extraire le token de la requête puis d'appeler la méthode "authenticate()" du AuthenticationManager
- Cela provoquera un appel à la méthode "retrieveUser()" de JwtAuthenticationProvider dans laquelle je vérifie le token (validité), récupère le username qu'il contient, récupère les authorisations en BD associées puis créé l'AuthenticatedUser

Plus tard je passerai sur de l'OAuth2.

Mes questions:
- Dans jwtAuthenticationFilter(), pourquoi définir un bean pour l'authenticationManager? Pourquoi pas un @Autowired ou un new? Egalement, pourquoi un new pour le success handler (JwtAuthenticationSuccessHandler) et pas un @Autowired vu qu'il déclaré avec @Component (je me suis basé sur un exemple trouvé)?
- Dans un exemple, j'ai vu que le bean daoAuthenticationProvider était déclaré mais je ne comprend pas son utilité car je ne l'avais pas avant (je souhaite hasher le mot de passe avec BCrypt ce que je n'avais pas dans mon précédent exemple donc c'est peut être pour ca).
- Il y a des "conversions" dont je ne suis pas sûr comme pour pattern="/rest/**" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless" ou before="FORM_LOGIN_FILTER" ou bien l'authenticationManager ou bien encore <security:global-method-security pre-post-annotations="enabled" />.
- Je ne comprend si .httpBasic() est utile dans mon cas car je vérifie la présence du token et sa validité dans le header de la requête avec mon filtre personnalisé.
- Lors de l'authentification (appel au service correspondant), comment se passe la vérification du mot de passe avec BCrypt?

Pouvez-vous m'aider svp?

Merci d'avance.