Chercher
- Détails
- Catégorie : Spring
- Affichages : 43
III. Application avec Spring Security
1. Authentification par JWT
Après avoir discuté des éléments internes du framework Spring Security, configurons-le pour l'authentification "STATELESS" (sans état) avec un jeton JWT .
Pour personnaliser Spring Security pour l'utilisation de JWT, nous avons besoin d'une classe de configuration annotée avec @EnableWebSecurity . De plus, pour simplifier le processus de personnalisation, le framework expose une classe appelée WebSecurityConfigurerAdapter .On étend cette classe et on surcharge ses deux méthodes de manière à :
1) Configurer le gestionnaire d'authentification avec le bon fournisseur
2) Configurer la sécurité Web (URL publiques, URL privées, autorisation, etc.) ; voir ci-dessous
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // TODO configure authentication manager } @Override protected void configure(HttpSecurity http) throws Exception { // TODO configure web security } }
Dans une application classique , nous stockons les identités des utilisateurs dans une base de données. Ces identités sont mappées par l'entité User et leurs opérations CRUD sont définies par un référentiel UserRepo Spring Data.
Désormais, lorsque nous acceptons la demande d'authentification, nous devons récupérer l'identité correcte de la base de données à l'aide des informations d'identification fournies, puis la vérifier. Pour cela, nous avons besoin de l'implémentation de l'interface UserDetailsService, qui est définie comme suit :
public interface UserDetailsService { UserDetails loadUserByUsername (String username) throws UsernameNotFoundException ; }
Ici, nous pouvons voir qu'il est nécessaire de renvoyer l'objet qui implémente l'interface UserDetails, et notre entité User l'implémente (pour les détails d'implémentation.
Étant donné qu'il n'expose que le prototype à fonction unique, nous pouvons le traiter comme une interface fonctionnelle et fournir une implémentation sous la forme d'une expression lambda. Ici, l'appel de fonction auth.userDetailsService lancera l'instance DaoAuthenticationProvider à l'aide de notre implémentation de l'interface UserDetailsService et l'enregistrera dans le gestionnaire d'authentification. Avec le fournisseur d'authentification, nous devons configurer un gestionnaire d'authentification avec le schéma de codage de mot de passe correct qui sera utilisé pour la vérification des informations d'identification. Pour cela, nous devons exposer l'implémentation préférée de l'interface PasswordEncoder sous forme de bean. Dans notre exemple de projet, nous utiliserons l’algorithme de hachage de mot de passe bcrypt.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() .and() .formLogin() .and() .logout() .and() .csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder); } }
Dans le code ci-dessus, Spring Security est activé à l'aide de l'annotation @EnableWebSecurity. La méthode configure(HttpSecurity http) est utilisée pour configurer le contrôle d'accès, en spécifiant quelles URL nécessitent quels rôles accéder et que toute demande nécessite une authentification. La méthode formLogin() active l'authentification basée sur un formulaire, la méthode logout() active la prise en charge de la déconnexion et la méthode csrf().disable() désactive la protection CSRF. La méthode configure(AuthenticationManagerBuilder auth) est utilisée pour configurer l'authentification, en spécifiant quelle implémentation UserDetailsService utiliser pour obtenir les informations utilisateur et les mots de passe, et quelle implémentation PasswordEncoder utiliser pour la vérification du mot de passe.
...
- Détails
- Catégorie : Spring
- Affichages : 45
1. AuthenticationManager
1.1.1. La signature de AuthenticationManager
AuthenticationManager est l'interface qui a un rôle central pour l'authentification au sein d' une application dont la sécurité est gérée par Spring Security ; cette interface reçoit les requêtes des filtres et délègue la validation des informations des utilisateurs ( login et password) aux fournisseurs d'authentification (AuthenticationProvider ) disponibles; AuthenticationProvider gère un ou plusieurs fournisseurs d'authentification.
AuthenticationManager peut être considérée comme un coordinateur qui enregistre plusieurs fournisseurs et, en fonction du type de demande, envoie la requête d'authentification au bon fournisseur; elle possède une seule méthode appelée authenticate et a comme signature:
public interface AuthenticationManager { Authentication authenticate (Authentication authentication) throws AuthenticationException; }
La méthode authenticate a un paramétre de type Authentication et retourne une réponse de type Authentication ; cette façon de faire (voir le cours de java) nous permet de ne pas figer la façon dont l'interface Authentication sera implémentée.
.....
1.1.2. Exemple d'utilisation de AuthenticationManager
......
@Configuration
@EnableWebSecurity
public class SecurityConfig {
...... ....... @Bean public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); return authenticationManagerBuilder.build(); } .....
}
........
Pour Spring Security, une configuration rapide des détails des utilisateurs en mémoire, pour JDBC , LDAP ou pour l'ajout de UserDetailsService personnalisé, on se sert de AuthenticationManagerBuilder, L'exemple suivant montre une application qui configure l'AuthentificationManager global (parent) :
@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { ...
// ce qui concerne le web par exemple @Autowired public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("omara") .password("secret").roles("USER"); } }
......
......
1.2. AuthenticationProvider
L'interface AuthenticationProvider dérive de l'interface AuthentificationManager; L'implémentation courante de AuthenticationProvider est la classe ProviderManager ; AuthenticationProvider a une méthode supplémentaire par rapport à AuthenticationProvider pour permettre à l'appelant de demander s'il prend en charge une "Authentication" type donné car AuthenticationProvider traite des types spécifiques d’authentification; elle possède deux méthodes :
la méthode authenticate effectue l'authentification avec la demande et la méthode supports vérifie si le fournisseur prend en charge le type d'authentification indiqué. La signature de AuthenticationProvider est :
public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); }
L'argument Class<?> dans la méthode supports() est en réalité Class<? extends Authentication> (on lui demande uniquement s'il prend en charge quelque chose qui est transmis à la méthode Authenticate()). Un objet de type ProviderManager peut prendre en charge plusieurs mécanismes d'authentification différents dans la même application en déléguant à une chaîne de AuthenticationProviders. Si un ProviderManager ne reconnaît pas un type d’instance d’authentification particulier, ce dernier est ignoré.
Un ProviderManager a un parent facultatif, qu'il peut consulter si tous les fournisseurs renvoient null. Si le parent n'est pas disponible, une authentification nulle entraîne une AuthenticationException.
Parfois, une application dispose de groupes logiques de ressources protégées (par exemple, toutes les ressources Web qui correspondent à un modèle de chemin, tel que /api/**), et chaque groupe peut avoir son propre AuthenticationManager dédié. Souvent, chacun d’eux est un ProviderManager et ils partagent un parent. Le parent est alors une sorte de ressource « globale », agissant comme une ressource de secours pour tous les prestataires.
Une implémentation importante de l'interface souvent utilisé dans des projets est DaoAuthenticationProvider , qui récupère les informations de l'utilisateur à partir d'une implémentation de l'interface UserDetailsService.
1.3. Interface UserdetailsService
L'interface UserDetailsService est décrit comme une interface principale qui charge des données spécifiques à l'utilisateur .
Dans la plupart des cas d'utilisation, AuthenticationProvider permet d'extraire les informations relatives aux utilisateurs en fonction des informations d'identification stockées dans une base de données, pour pouvoir effectuer la validation. Ce cas d'utilisation étant si courant, les développeurs Spring Security ont décidé de définir UserDetailsService en tant qu'interface distincte qui expose la méthode unique "loadUserByUsername" qui accepte le nom d'utilisateur comme paramètre et renvoie l'objet d'identité de l'utilisateur.
.....
- Détails
- Catégorie : Spring
- Affichages : 2238
I. Spring Security: Généralités
1. Présentation
Spring est considéré comme un terme générique qui couvre unn ensemble de framework dont Spring Security dans l’écosystème Java. Spring Security est un framework d'authentification et d'autorisation puissant qu'on peut personnaliser ( customiser). Pour sécuriser des applications basées sur Spring, on l'utilise et lorsqu'on cherche à implémenter une solution de jeton JWT, il est logique de la baser sur Spring JWT. Malgré sa popularité, Spring Security n'est pas simple et direct à configurer. Dans Spring Security des termes son utilisés et il est important de comprendre leur signification.
1.1. L'authentification
Elle fait référence au processus de vérification de l'identité d'un utilisateur, sur la base des informations d'identification fournies. Un exemple courant consiste à saisir un nom d'utilisateur et un mot de passe lorsque vous vous connectez à un site Web.
Ici vous pouvez y voir une réponse à la question "Qui êtes-vous ?" qui nécessite de donne un nom mais aussi un gage qui permet d'être sûr que c'est vraiment et c'est un mot de passe . Muni de ses informations on vérifie ( le système) que vous êtes connue et enregistré sur le système. Une fois cette reconnaissance faite il va falloir savoir quelles sont vos autorisations
1.2. L'autorisation
Elle fait référence au processus permettant de déterminer si un utilisateur dispose de l'autorisation appropriée pour effectuer une action particulière ou lire des données particulières, en supposant que l'utilisateur est authentifié avec succès. Vous pouvez y voir une réponse à la question Un utilisateur peut-il faire ?
1.3. La classe Principal
Elle fait référence à l'utilisateur actuellement authentifié.
1.4. L'autorité accordée
Elle fait référence à l'autorisation de l'utilisateur authentifié.
1.5. Le rôle
il fait référence à un groupe d'autorisations de l'utilisateur authentifié
Une fois qu'on a défini ces termes, regardons de prêt l'architecture ou plutôt comment fonctionne Spring Security. L'architecture de Spring Security est conçue de telle sorte que l'on puisse distinguer l'authentification et l'autorisation puis de pouvoir gérer des stratégies et des points d'extension pour les deux.
2. Architecture de Spring Security
Les filtres sont des composants Java enfichables qu'on utilise pour intercepter et traiter des requêtes clientes avant qu'elles ne soient envoyées aux servlets; pour une application basée sur une servlet, Le conteneur de servlets crée un objet de type FilterChain qui contient les instances des différents filtres et de la Servlet de l'application.
comme Spring est un framework basé sur une servlet en l'occurence DispatcherServlet, Si on utilise Spring Security , le système de filtres de Spring Security "Spring Security Filter Chain" est pris en charge par la chaine de filtrage du conteneur de servlets au niveau de FilterChaineProxy (voir shéma ci-dessous) par un filtre nommé DelegatingFilterProxy; celui-ci permet de faire le pont entre le cycle de vie du conteneur de servlets et ApplicationContext de Spring.
On peut enregistrer DelegatingFilterProxy via les mécanismes du conteneur de Servlet standard, mais déléguer tout le travail à un Spring Bean qui implémente Filter.
Le client envoie une requête à l'application et le conteneur crée un filtre de type FilterChain, qui contient les instances de filtres et la servlet qui doivent traiter les requêtes de type HttpServletRequest, en fonction de l'URI de la requête. Dans une application Spring MVC, le/la Servlet qui traite ces requêtes est une instance de DispatcherServlet. Tout au plus, un/une servlet peut gérer une seule requête de type HttpServletRequest et d'une reponse de type HttpServletResponse.
Spring Security ne sécurise pas les réseaux ou les ordinateurs, mais les applications: il intervient dans le dialogue entre l'application et l'utilisateur (ou entre deux applications). Ce dialogue est géré par le servlet Spring DispatcherServlet , qui redirige les requêtes http vers les classes contrôleur de l'application. En résumé, le rôle de Spring Security est d'insérer des opérations dans cette interaction, grâce à un ensemble de filtres de servlets. Ce groupe de filtres est la chaîne de filtres de Spring Security.
3. Chaîne de filtres de Spring Security
3.1. Généralités
Comme il est précisé ci-dessus, dans une application basée sur des servlets, les requêtes en entrée passent par un certain nombre de filtres; il en est de même des filtres de Spring Security. L'image suivante montre la superposition typique des gestionnaires de filtres pour une seule requête HTTP.
Avant de commencer à personnaliser la configuration, discutons d'abord du fonctionnement de l'authentification de Spring Security en coulisses. Le diagramme suivant montre que Spring Security est un ensemble de filtres; le traitement des requêtes en entrée est géré par "AuthenticationManager" ; le flux est ensuite dispatcher aux différents "AuthentificationProvider".
Lorsqu'on ajoute le framework Spring Security à une application, il enregistre automatiquement une chaîne de filtres qui interceptent toutes les requêtes entrantes. Cette chaîne se compose de différents filtres, et chacun d'entre eux gère un cas d'utilisation particulier.
Cependant, plusieurs filtres peuvent être utilisés pour par exemple :
- Empêchez l'appel des instances de filtre en aval ou certains appels du servlet. Dans ce cas, le filtre écrit généralement la réponse HttpServletResponse.
- Modifiez la requête de type HttpServletRequest ou la réponse de type HttpServletResponse utilisé par les instances de filtre en aval ou du servlet.
La puissance du filtre vient de la FilterChain qui y est transmise.
La chaîne de filtrage effectue des actions avant d'atteindre le Servlet DispatcherServlet, afin de vérifier si une requête provient d'un utilisateur authentifié et autorisé, avant de la laisser aller vers les contrôleurs. En résumé La chaîne de filtrage traite 2 concepts fondamentaux :
authentification : l'utilisateur doit être identifié par une combinaison nom d'utilisateur/mot de passe.
autorisations : les utilisateurs ne sont pas égaux quant aux opérations qu'ils sont autorisés à effectuer. A titre d'exemple, un utilisateur qui n'est pas administrateur ne doit pas être autorisé à modifier le compte d'un autre utilisateur.
3.2. Exemples d'actions traitées par les filtre:
- Vérifiez si l'URL demandée est accessible au public, en fonction de la configuration.
- En cas d'authentification basée sur la session, vérifiez si l'utilisateur est déjà authentifié dans la session en cours.
- Vérifiez si l'utilisateur est autorisé à effectuer l'action demandée, et ainsi de suite. Un détail important qu'il ne faut pas oublier c'est que tous les filtres Spring Security sont enregistrés avec un ordre de traitement; les ordres les plus bas sont les premiers invoqués. Pour certains cas d'utilisation, si on souhaite placer un filtre personnalisé devant ceux de Spring Security, on doit faire la commande. Cela peut être fait avec la configuration suivante :
spring.security.filter.order=10
Une fois que nous aurons ajouté cette configuration à notre fichier "application.properties", nous aurons de l'espace pour 10 filtres personnalisés devant les filtres de Spring Security.
3.3. Exemple
......
4. Chaîne de filtres par défaut
Lors du lancement d'une application implémentant Spring Security, l'un des premiers logs apparaissant dans la console ressemble à:
2020-02-25 10:24:27.875 INFO 11116 — — [ main] o.s.s.web.DefaultSecurityFilterChain : Création d'une chaîne de filtres : toute requête […]
Ce journal répertorie les filtres par défaut implémentés par Spring Security. Ci-après, une liste ordonnée des filtres constituant la chaîne de filtres par défaut (Spring Security v5.4.2).
WebAsyncManagerIntegrationFilter : ce type est comme le ciment entre le SecurityContext et le WebAsyncManager, permettant de remplir le SecurityContext pour chaque requête.
SecurityContextPersistenceFilter : envoie les informations du SecurityContextRepository au SecurityContextHolder, ce dernier étant nécessaire au processus d'authentification, qui nécessite un SecurityContext valide.
HeaderWriterFilter : ajoute des en-têtes à la requête en cours. Ce filtre est particulièrement utile pour prévenir certaines attaques courantes en ajoutant des en-têtes comme X-Frame-Options, X-XSS-Protection et X-Content-Type-Options (voir la partie sur la protection générale ci-dessous)
CsrfFilter : ajoute une protection contre les attaques Cross-Site Request Forgery, en impliquant un jeton, qui est généralement enregistré sous forme de cookie dans la HttpSession. Il est courant d'appeler ce filtre avant toute requête pouvant changer l'état de l'application (principalement POST, PUT, DELETE et parfois OPTIONS).
LogoutFilter : gère le processus de déconnexion en appelant plusieurs lougoutHandlers chargés d'effacer le contexte de sécurité, d'invalider la session utilisateur, de rediriger vers la page par défaut…
UsernamePasswordAuthenticationFilter : analyse la soumission d'un formulaire d'authentification, qui doit fournir un nom d'utilisateur et un mot de passe. Ce filtre est activé par défaut sur l'URL /login.
DefaultLoginPageGeneratingFilter : construit une page d'authentification par défaut, à moins qu'elle ne soit explicitement inactivée. Ce filtre est la raison pour laquelle une page de connexion apparaît lors de l'implémentation de Spring Security, avant même que le développeur n'en crée une personnalisée.
DefaultLogoutPageGeneratingFilter : construit une page de déconnexion par défaut, à moins qu'elle ne soit explicitement inactivée.
BasicAuthenticationFilter : vérifie si une demande inclut un en-tête d'authentification de base et tente de se connecter avec le nom d'utilisateur et le mot de passe lus dans cet en-tête.
RequestCacheAwareFilter : vérifie dans le cache si la requête en cours est similaire à une ancienne afin d'accélérer son traitement.
SecurityContextHolderAwareRequestFilter : offre de multiples fonctionnalités pour chaque requête, notamment concernant le processus d'authentification : récupérer les informations des utilisateurs, vérifier s'ils sont authentifiés (et sinon, offrir la possibilité de s'authentifier via le gestionnaire d'authentification), obtenir leurs rôles, proposer de se déconnecter via les gestionnaires de déconnexion, maintenant le contexte de sécurité sur plusieurs threads…
AnonymousAuthenticationFilter : fournit un objet d'authentification au détenteur du contexte de sécurité s'il n'y en a pas.
SessionManagementFilter : vérifie si un utilisateur est authentifié depuis le début de la requête, et dans ce cas, procède aux vérifications liées à la session (à titre d'exemple, vérifie si plusieurs connexions simultanées sont actuellement en cours d'utilisation).
ExceptionTranslationFilter : gérez les exceptions AccessDeniedException et AuthenticationException levées par filterChain. Ce filtre est essentiel pour que l'interface graphique reste cohérente lorsque des erreurs se produisent, car il constitue le pont entre les exceptions Java et les réponses http.
FilterSecurityInterceptor : vérifie si les rôles de l'utilisateur correspondent aux exigences d'autorisation pour la demande en cours.
........
.......
- Détails
- Catégorie : Spring
- Affichages : 1500
Servlet Authentication Architecture
I. SecurityContextHolder et SecurityContext
Spring Security est un framework robuste pour la sécurisation des applications Java. Ses deux composants essentiels sont SecurityContext et SecurityContextHolder. Comprendre ces composants est crucial pour gérer l'authentification et récupérer les informations spécifiques à l'utilisateur, comme le nom d'utilisateur de l'utilisateur actuellement connecté.
SecurityContextHolder
Au cœur du modèle d'authentification de Spring Security se trouve la classe SecurityContextHolder. Il contient le SecurityContext. Le SecurityContextHolder est l'endroit où Spring Security stocke les détails de la personne authentifiée. L'objet Conteneur SecurityContext stocke les informations d'authentification et de sécurité de l'utilisateur actuellement connecté. En son sein l'objet SecurityContext contient un objet Authentication, qui représente le principal (l'utilisateur) et les droits qui lui sont accordés (rôles/autorisations).Spring Security ne se soucie pas de la manière dont le SecurityContextHolder est renseigné. S'il contient une valeur, il est utilisé comme utilisateur actuellement authentifié. Le moyen le plus simple d'indiquer qu'un utilisateur est authentifié est de définir directement le SecurityContextHolder
......
Authentication - Can be the input to AuthenticationManager to provide the credentials a user has provided to authenticate or the current user from the SecurityContext.
GrantedAuthority - An authority that is granted to the principal on the Authentication (i.e. roles, scopes, etc.)
AuthenticationManager - the API that defines how Spring Security’s Filters perform authentication.
ProviderManager - the most common implementation of AuthenticationManager.
AuthenticationProvider - used by ProviderManager to perform a specific type of authentication.
Request Credentials with AuthenticationEntryPoint - used for requesting credentials from a client (i.e. redirecting to a log in page, sending a WWW-Authenticate response, etc.)
AbstractAuthenticationProcessingFilter - a base Filter used for authentication. This also gives a good idea of the high level flow of authentication and how pieces work together.
- Détails
- Catégorie : Spring
- Affichages : 5286
III. Autres modules
Il y a quelques autres modules importants comme les modules AOP, Aspects, Instrumentation, Web et Test:
- Le module AOP fournit une implémentation de programmation orientée aspect vous permettant de définir des intercepteurs de méthode et des Pointcuts pour découper proprement le code qui implémente des fonctionnalités à séparer .
- Le module Aspects fournit l'intégration avec AspectJ, qui est à nouveau un framework AOP puissant et mature .
- Le module Instrumentation fournit un support d'instrumentation de classe et des implémentations de chargeur de classes à utiliser dans certains serveurs d'applications .
- Le module Messaging (module de messagerie) prend en charge STOMP en tant que sous-protocole WebSocket à utiliser dans les applications. Il prend également en charge un modèle de programmation d'annotation pour le routage et le traitement des messages STOMP à partir des clients WebSocket .
- Le module Test (module de teste) prend en charge les tests des composants Spring avec les frameworks JUnit ou TestNG .
...