Spring Security Basic Introduction
Je ne donnerai pas trop d'introduction à la sécurité du printemps ici. Pour plus de détails, veuillez vous référer à la documentation officielle.
Je ne parlerai que des fonctions principales de Springsecurity:
Construction de l'environnement de base
Ici, nous utilisons Springboot comme cadre de base du projet. J'utilise la méthode Maven pour la gestion des packages, alors nous donnons ici d'abord la méthode d'intégration de la sécurité de Spring.
<Dendecces> ... <Dependency> <GroupId> org.springFramework.boot </rom grouped> <ArtefactId> printemps-boot-starter-security </retifactid> </dependency> ... </dedences>
Ensuite, établissez une interface de demande de couche Web
@ RestController @ requestmapping ("/ user") public class userController {@getMapping public String getUsers () {return "Hello Spring Security"; }}Ensuite, vous pouvez exécuter le projet directement et appeler l'interface pour voir l'effet.
Appel via la page Web
Nous faisons d'abord l'appel d'interface via le navigateur et accédons directement à http: // localhost: 8080 / utilisateur. Si l'interface est accessible normalement, "Hello Spring Security" doit être affiché.
Mais nous ne pouvons pas y accéder normalement, et la boîte d'entrée d'authentification dans la figure ci-dessous apparaît
En effet, à Springboot, la sécurité de ressort par défaut est efficace. À l'heure actuelle, les interfaces sont protégées et nous devons passer la vérification pour y accéder normalement. Spring Security fournit un utilisateur par défaut, le nom d'utilisateur est l'utilisateur et le mot de passe est généré automatiquement lorsque le projet est démarré.
Lorsque nous vérifions le journal de démarrage du projet, nous trouverons le journal suivant
Utilisation du mot de passe de sécurité par défaut: 62ccf9ca-9fbe-4993-8566-8468cc33c28c
Bien sûr, le mot de passe que vous voyez doit être différent du mien. Nous nous connectons directement avec l'utilisateur et le mot de passe dans le journal de démarrage.
Après avoir enregistré avec succès, vous passez à la page où l'interface est appelée normalement.
Si vous ne souhaitez pas activer Spring Security depuis le début, vous pouvez configurer ce qui suit dans le fichier de configuration:
# Security Activer Security.basic.enabled = false
La boîte de connexion que je viens de voir a été fournie par Springsecurity, qui s'appelle httpbasiclogin. Ce n'est pas ce que nous voulons sur notre produit. Notre frontal effectue généralement une vérification de la connexion des utilisateurs via la soumission du formulaire, nous devons donc personnaliser notre propre logique d'authentification.
Personnaliser la logique d'authentification des utilisateurs
Chaque système doit avoir son propre ensemble de systèmes utilisateur, nous devons donc personnaliser notre propre logique d'authentification et notre interface de connexion.
Ici, nous devons configurer Springsecurity en conséquence
@ConfigurationPublic Class BrowerseCurityConfig étend WebSecurityConfigurerAdapter {@Override Protected void Configure (httpSecurity http) exception {http.formlogin () // Définir la page de connexion à transférer lorsque l'utilisateur est requis pour se connecter. et qui n'ont pas besoin d'être protégés.anyRequest () // Pour toute demande, vous pouvez accéder à .Authenticated (); }}Ensuite, configurez la logique d'authentification de l'utilisateur, car nous avons notre propre système utilisateur.
@ComponentPublic class MyUserDetailSService implémente userDetailSService {private logger logger = loggerfactory.getLogger (getClass ()); @Override public UserDetails LoadUserByUserName (String Username) lève UserNamenotFoundException {Logger.info ("User's Username: {}", nom d'utilisateur); // TODO selon le nom d'utilisateur, trouver le mot de passe correspondant et encapsuler les informations de l'utilisateur et retourner. Les paramètres sont: Nom d'utilisateur, mot de passe, autorisation utilisateur utilisateur utilisateur = new User (useraMe, "123456", AuthorityUtils.commaséparatedStringToAuthorityList ("admin")); RETOUR UTILISATEUR; }} Nous n'avons pas effectué trop de vérification ici. Le nom d'utilisateur peut être rempli à volonté, mais le mot de passe doit être "123456" afin que nous puissions nous connecter avec succès.
Dans le même temps, nous pouvons voir que le troisième paramètre de l'objet utilisateur représente ici les autorisations de l'utilisateur actuel, et nous le définissons sur "Admin".
Exécutez le programme pour le tester et vous constaterez que l'interface de connexion a changé.
En effet, nous avons configuré http.formLogin() dans le fichier de configuration
Remplissons simplement un utilisateur ici, puis remplissons une mauvaise version (non-123456). Cela provoquera une erreur de vérification:
Dans le même temps, sur la console, l'utilisateur que vous venez de remplir lorsque vous vous connectez sera également imprimé.
Essayons maintenant de vous connecter avec le mot de passe correct. Vous pouvez constater qu'il passera la vérification et sautera sur la page d'appel d'interface correcte.
Userdetails
Tout à l'heure, lorsque nous écrivions MyUserDetailsService , nous avons implémenté une méthode et renvoyé un UserDetails . Cet userdetails est un objet qui encapsule les informations utilisateur, qui contient sept méthodes
Interface publique UserDetails étend Serializable {// Collection d'informations d'autorisation encapsulée <? étend l'autorité accorde> getAuthorities (); // Strime d'information de mot de passe getPassword (); // Login Username String getUserName (); // si le compte expire Boolean IsAccountNonexpired (); // si le compte est congelé booléen IsAccountNonlocked (); // Le mot de passe du compte expire, généralement certains systèmes avec des exigences de mot de passe élevés l'utiliseront. Comparé à l'utilisateur est nécessaire pour réinitialiser le mot de passe de temps en temps booléen isCredentialSnOnexpired (); // Le compte est-il disponible? Boolean iseNabled ();}Lorsque nous retournons l'utilisateur de la classe d'implémentation UserDetails, nous pouvons définir les paramètres correspondants via la méthode du constructeur utilisateur
Cryptage et décryptage de mot de passe
Il y a une interface de mot de passe-code dans Springsecurity
Interface publique PasswordEncoder {// Crypt le code de mot de passe encode (CharSequence Var1); // Déterminer le mot de passe pour faire correspondre les matchs booléens (CharSequence Var1, String var2);} Nous avons juste besoin d'implémenter cette interface nous-mêmes et de la configurer dans le fichier de configuration.
Ici, je vais le tester temporairement avec une classe d'implémentation fournie par défaut
// BrowersECURITYCONFIG @BeanPublic PasswordEncoder PasswordEncoder () {return new BCryptPasswordEncoder (); }Utilisation du chiffrement:
@ComponentPublic class MyUserDetailSService implémente userDetailSService {private logger logger = loggerfactory.getLogger (getClass ()); @Autowired Private MotwordEncoder PasswordEncoder; @Override public UserDetails LoadUserByUserName (String Username) lève UserNamenotFoundException {Logger.info ("User's Username: {}", nom d'utilisateur); String Motword = PasswordEncoder.encode ("123456"); logger.info ("mot de passe: {}", mot de passe); // Les paramètres sont: Nom d'utilisateur, mot de passe, autorisation utilisateur utilisateur utilisateur = nouvel utilisateur (nom d'utilisateur, mot de passe, autorité. RETOUR UTILISATEUR; }}Ici, nous cryptons simplement 123456. Nous pouvons effectuer des tests et constater que le mot de passe imprimé à chaque fois est différent. C'est le rôle du BcryptPasswordEncoder configuré.
Logique d'authentification utilisateur personnalisée
Page de connexion personnalisée
Dans les tests précédents, l'interface de connexion par défaut a toujours été utilisée. Je crois que chaque produit a sa propre conception d'interface de connexion, nous apprendrons donc comment personnaliser la page de connexion dans cette section.
Écrivons d'abord une page de connexion simple
<! Doctype html> <html lang = "en"> <éadf> <meta charset = "utf-8"> <itle> page de connexion </ title> </ head> <body> <h2> page de connexion personnalisée </h2> <form action = "/ user / connex type = "text" name = "username"> </ td> </ tr> <tr> <td> mot de passe: </td> <td> <entrée type = "mot de passe" name = "mot de passe"> </td> </ tr> <tr> <td Colspan = "2"> <bouton type = "Soumide"> Login </ Button> </td> </tr> </p> </ Table>
Après avoir terminé la page de connexion, vous devez le configurer pour Springsecurity
// BrowersecurityConfig.java@overrideprotected void configure (httpSecurity http) lève une exception {http.formlogin () // définir la page de connexion à transférer lorsque l'utilisateur doit se connecter. page.loginprocessingUrl ("/ user / ligin") // Interface de connexion personnalisée.and () .AuthorizeRestes () // Définir les URL à protéger et lesquelles ne doivent pas être protégées.antmatchers ("/ login.html"). .Authenticated () .and () .csrf (). Disable (); // désactiver la protection CSRF}De cette façon, chaque fois que nous accéderons à l'interface protégée, nous serons transférés sur la page Login.html
Gérer différents types de demandes
Parce que maintenant, les extrémités avant et arrière sont généralement séparées, le back-end fournit des interfaces pour l'appel avant et renvoie les données de format JSON à l'avant. Comme précédemment, l'interface protégée a été appelée et le saut de page a été directement redirigé. Il est acceptable du côté Web, mais il n'est pas possible du côté de l'application, nous devons donc effectuer un traitement supplémentaire.
Voici une idée simple de trier
Tout d'abord, écrivez un contrôleur personnalisé et sautez-y lorsque l'authentification d'identité est requise.
@RestControllerPublic Class BrowseSeSecurityController {private logger logger = loggerfactory.getLogger (getClass ()); // mise en cache et récupération des informations de demande d'origine privées requestcache requestCache = new httpSessionRequestCache (); // utilisé pour rediriger privé redirectStratergy redirectStrategy = new DefaulTreDirectStrategy (); / ** * Lorsque l'authentification de l'identité est requise, sautez sur * @param demande * @param réponse * @return * / @requestmapping ("/ authentication / require") @ResponSestatus (code = httpstatus.unAuthorized) public basseResponse DeviceAuthenication (httpServLetRequest request, httpserRespERSPERS a réponse) SaveDequest = requestCache.getRequest (request, réponse); if (SaveDequest! = null) {String TargetUrl = SaveDequest.getReDirectUrl (); Logger.info ("La demande pour déclencher un saut est:" + TargetUrl); if (stringUtils.endsWithIgnoreCase (TargetUrl, ".html")) {redirectStrategy.sendRedirect (demande, réponse, "/login.html"); }} return new BaseSesponse ("Le service accessible nécessite une authentification d'identité, veuillez guider l'utilisateur vers la page de connexion"); }}Bien sûr, le fichier de configuration doit être modifié en conséquence, donc je ne publierai pas le code ici. Il s'agit d'ouvrir l'interface.
Extensions:
Ici, nous écrivons l'interface accessible à partir d'une page Web, puis passons à la page "/login.html". En fait, nous pouvons l'étendre et configurer l'adresse de saut dans le fichier de configuration, ce qui sera plus pratique.
Traitement personnalisé Connexion réussie / Échec
Dans les tests précédents, la redirection de la page a été effectuée après une connexion réussie.
Dans le cas de la séparation des extrémités avant et arrière, si nous nous connectons avec succès, nous devrons peut-être renvoyer les informations personnelles de l'utilisateur à l'avant au lieu de sauter directement. Il en va de même pour l'échec de la connexion.
Cela implique deux interfaces dans Spring Security AuthenticationSuccessHandler et AuthenticationFailureHandler . Nous pouvons implémenter cette interface et la configurer en conséquence. Bien sûr, le cadre a une classe d'implémentation par défaut. Nous pouvons hériter de cette classe d'implémentation et personnaliser notre entreprise
@Component ("MyAuthenCtiationSuccessHandler") Classe publique MyAuthenCtiationSuccessHandler étend SimpleUrlAuthenticationsuCcessHandler {private logger logger = loggerfactory.getLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void onAuthenticationsUCCESS (demande httpservletRequest, réponse httpservletResponse, authentification authentification) lance ioexception, servlexception {logger.info ("connecter réussi"); réponse.setContentType ("application / json; charset = utf-8"); réponse.getWriter (). Write (objectMapper.WriteValueAsString (authentification)); }} Ici, nous renvoyons une chaîne JSON via la réponse.
Le troisième paramètre de cette méthode, Authentication , contient les informations d'utilisateur de connexion (UserDetails), les informations de session, les informations de connexion, etc.
@Component ("MyAuthenCtiationFailureHandler") Classe publique MyAuthenctiationFailureHandler étend SimpleUrlAuthenticationFailureHandler {private logger logger = loggerfactory.getLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void onAuthenticationFailure (demande httpservletRequest, réponse httpServletResponse, exception d'authentificationxception) lève ioException, servlexception {logger.info ("Login a échoué"); réponse.setstatus (httpstatus.internal_server_error.value ()); réponse.setContentType ("application / json; charset = utf-8"); réponse.getWriter (). WRITE (objectMapper.WriteValueAsString (new BaseResponse (exception.getMessage ()))); }} Le troisième paramètre de cette méthode AuthenticationException , comprend des informations sur l'échec de la connexion.
De même, il est toujours nécessaire de le configurer dans le fichier de configuration. Je ne publierai pas tout le code ici, seules les instructions correspondantes sont publiées.
.SuccessHandler (MyAuthenticationsUCcessHandler) // Couchure Connexion Handles avec succès.FailureHandler (MyAuthenticationFailureHandler) // Gandoues de défaillance de connexion personnalisées
Code
Vous pouvez cliquer sur moi pour afficher le code complet
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.