Shiro
Shiro est un projet open source sous Apache, nous l'appelons Apache Shiro. Il s'agit d'un cadre de sécurité très facile à utiliser avec des projets Java, fournissant l'authentification, l'autorisation, le chiffrement et la gestion de session. Comme Spring Security, il s'agit d'un cadre de sécurité d'autorisation. Cependant, par rapport à Spring Security, Shiro utilise une méthode d'autorisation relativement simple, facile à comprendre et facile à utiliser. Shiro est un cadre léger. Il est beaucoup plus simple que la sécurité et n'est pas aussi compliqué que la sécurité. Pour des présentations plus détaillées, vous pouvez essentiellement apprendre de son site officiel (http://shiro.apache.org/) qu'il offre principalement les fonctions suivantes:
(1) Authentification (authentification)
(2) Autorisation (autorisation)
(3) Gestion de session (gestion de session)
(4) cryptographie (cryptage)
Tout d'abord, le service d'authentification, c'est-à-dire, à travers elle, vous pouvez compléter l'authentification de l'identité, lui permettant de déterminer si l'utilisateur est un véritable membre.
Deuxièmement, le service autorisé, à le dire franchement, est le service "Contrôle d'accès", c'est-à-dire, laissez-lui identifier les autorisations de l'utilisateur. Pour le dire franchement, c'est pour lui donner les autorisations d'opération en jugeant quel rôle l'utilisateur est.
Ensuite, il y a le service de gestion de session. Pour le moment, un cadre de gestion de session indépendant est différent de la session HTTP que nous connaissons.
Enfin, elle fournit également des services de cryptographie (cryptage), encapsulant de nombreux algorithmes cryptographiques.
Aujourd'hui, je ne dirai pas tout à ce sujet et je me concentrerai sur sa fonction de gestion de la conversation. En fait, c'est quelque chose que presque tous les sites Web devraient être impliqués.
Avant de parler du service de gestion de session de Shiro, passons en revue comment nous avons fait la gestion de session précédente.
1. Au début, nous avons utilisé directement le mécanisme de session HTTP du serveur Web. Autrement dit, si l'utilisateur arrive pour la première fois, le conteneur Web créera une session pour la demande, puis stockera la session. En passant le SessionId correspondant en tant que cookie au client.
Si le client envoie à nouveau une demande à ce serveur, le SessionID sera automatiquement ramené. Ensuite, le serveur Web déterminera si la session est toujours en mémoire en fonction du SessionID apporté par le client (la session a un temps d'expiration et peut être configurée dans le fichier web.xml). Si la session correspondante ne peut être trouvée, cela signifie que le temps d'expiration de la session s'est écoulé. À l'heure actuelle, le serveur Web créera à nouveau une session pour cela, puis transmettra le nouveau SessionID au client comme auparavant.
Par conséquent, nous pouvons utiliser ce mécanisme pour gérer la session de connexion de l'utilisateur dans le programme. Par exemple, une fois la première connexion de l'utilisateur, nous stockons les informations de base de l'utilisateur dans la session (par exemple: session.setAttribute("user", "userInfo") ). La prochaine fois que l'utilisateur sera à nouveau rendu compte, nous obtenons les informations de l'utilisateur de la session en cours en fonction des informations de l'utilisateur
( session.getAttribute("user") ) pour déterminer si l'utilisateur a expiré. S'il ne peut pas être obtenu, l'utilisateur sera invité à se connecter à nouveau.
2. La deuxième méthode consiste à transférer l'endroit où les informations sont stockées vers des supports tiers, tels que Cache, MemeCache ou Redis. Cette méthode est principalement adoptée en raison de l'émergence de systèmes distribués.
Dans ce cas, nous devons générer nous-mêmes le sessiond. Généralement, nous utiliserons un préfixe défini ( user:login:token ) et ajouterons l'utilisateur ou l'horodatage. Ensuite, nous utiliserons ce SessionID comme clé de cache, et les informations de l'utilisateur comme valeur, et la stockerons dans le cache, et définir le temps d'invalidation:
jedisclient.set (tokenkey, jsonutil.tojSontring (userInfo)); jedislient.expire (tokenkey, token_lose_seconds);
Nous devons également transmettre la clé de token générée au client via des cookies: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);
De cette façon, lorsque l'utilisateur visite la prochaine fois (définit un intercepteur), nous pouvons éliminer la clé de token correspondante à partir du cookie, puis utiliser cette clé de token pour accéder au cache pour récupérer la valeur correspondante. S'il ne peut pas être obtenu, cela signifie que la clé a expiré et que l'utilisateur est invité à se connecter à nouveau.
Remarque: le tokenkey est important, c'est le centre reliant le côté cache et le client.
3. Le dernier est notre méthode Shiro, et l'idée est similaire. Le code est assez simple, je vais donc télécharger le code:
1) Créez un nouveau fichier ApplicationContext-Shiro.xml:
<? xml version = "1.0" Encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: context = "http://www.springframework.org/schema/context" xmlns: p = "http://www.springframework.org/schema/p" xmlns: aop = "http://www.springframework.org/schema/tx" xmlns: xsi = "http://www.w3.org/2001/xmlma xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/springframeworks http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0. id = "shirofilter"> <propriété name = "SecurityManager" ref = "SecurityManager"> </ propriété> <propriété name = "Loginurl" value = "/ loginpage"> </ propriété> <propriété name = "UnauthorizedUrl" value = "/ pages / unauthorized.jsp" /> <propriété = "FilterChainDefinitions"> <value> / logout = anon </value> </ propriété> </ bean> <an bean> <propriété name = "staticMethod" value = "org.apache.shiro.securityutils.setsecuritymanager"> </ propriété> <propriété name = "arguments" ref = "SecurityManager"> </preper> </ank Ref = "CacheManager"> </ Property> <propriété name = "SessionManager" Ref = "SessionManager"> </ Property> </Ean> <Bean Id = "SessionManager"> <Property Name = "SessionDao" Ref = "SessionDao"> </ Bean> // Cette classe doit être mise en œuvre <Bean id = "CacheManager"> </EAND>
2) Configurez le filtre correspondant dans web.xml:
<filter> <filter-name> shirofilter </ filter-name> <filter-class> org.springframework.web.filter.delegatingfilterproxy </filter-Class> <Init-Param> <Am paraming-name> TargetFilterLifECycle </ param-name> <param-value> true </onsam -value> <mapping-mappant> <filtre-name> shirofilter </filter-name> <Url-sattern> / * </ url-potern> </filter-mapping>
3) Rédiger une classe d'implémentation, hériter de l'abstractSessionDAO et implémenter la méthode correspondante.
package com.jdd.core.shiro; import com.smart.core.redis.redismanager; import org.apache.shiro.session.session; import org.apache.shiro.session.unknownsexception; import org.apache.shiro.sesession org.springframework.beans.factory.annotation.autowired; import org.springframework.util.serializationutils; import java.io. *; import java.util.arraylist; import java.util.collection; classe publique MySessionDao albumsessiondao {@Autowired redismisMermer; @Override public void Update (Session Session) lève unponseSessionException {redisManager.set (SerializationUtils.serialize (session.getId (). ToString ()), SerializationUtils.serialize (session)); redismanager.expire (serializationUtils.serialize (session.getId (). ToString ()), 60); } @Override public void Delete (Session Session) {redisManager.del (SerializationUtils.serialize (session.getId (). ToString ())); } @Override public Collection <Session> getActivesessions () {return new ArrayList <Session> (); } @Override Protected Serializable DOCreate (Session Session) {// C'est à ce moment que vous accédez pour la première fois, créez SessionId Serializable Sid = this.GenerateSessionID (session); AssignSessionId (Session, SID); redismanager.set (serializationUtils.serialize (session.getId (). toString ()), serializationUtils.serialize (session)); redismanager.expire (serializationUtils.serialize (session.getId (). ToString ()), 60); Retour SID; } @Override Protected Session DoreadSession (Serializable Serializable) {// Cette méthode est en fait de lire la session via SessionID. Chaque fois que vous le lisez, le temps de défaillance doit être réinitialisé l'octet [] aa = redismanager.get (serializationUtils.serialize (serializable.toString ())); Session Session = (Session) SerializationUtils.deserialize (aa); redismanager.set (serializationUtils.serialize (serialisable.toString ()), serializationUtils.serialize (session)); redismanager.expire (SerializationUtils.serialize (Serializable.ToString ()), 60); Session de retour; }}4) L'étape suivante consiste à obtenir la session de Shiro dans la logique après la connexion réussie, puis à définir les informations de l'utilisateur
package com.smart.controller; import com.smart.pojo.user; import com.smart.service.userservice; import org.apache.shiro.securityutils; import org.apache.shiro.mgt.securitymanager; import org.apache.shiro.subject.subject; import org.slf4j.logger; org.slf4j.loggerfactory; import org.springframework.beans.factory.annotation.autowired; import org.springframework.steretype.controller; import org.springframework.ui.model; import org.springframework.web.bind.annotation. *; javax.servlet.http.httpservletRequest; Importer javax.servlet.http.httpservletResponse; @ contrôleur @ requestmapping ("/ user") public class userController {@Autowired Private Service Service Service; @Autowired Private SecurityManager SM; // Inject SecurityManager Logger Private Logger = LoggerFactory.getLogger (userController.class); @RequestMapping (value = "/ loginpage") String public LoginPage () {return "user / userLogin"; } @RequestMapping (value = "/ userlogin", méthode = requestMethod.post) public chaîne userLogin (@RequestParam (value = "name") String name, @requestParam (value = "pwd") String pwd, modèle modèle) {logger.info ("entrez userlogin ..."); User user = userService.getUserByNameAndPassword (nom, pwd); if (user == null) {logger.info ("L'utilisateur n'existe pas ..."); Model.AddAttribute ("Login_error", "Nom d'utilisateur ou erreur de mot de passe"); return "User / UserLogin"; } SecurityUtils.SetSecurityManager (SM); Sujet currentUser = SecurityUtils.getSubject (); currentUser.getSession (). setAttribute ("login_user", utilisateur); retourner "rediriger: / employé / liste"; }}Obtenez l'utilisateur actuel, dans Shiro, c'est le thème, puis obtenez la session correspondante et définissez les informations de l'utilisateur. Cela ressemble-t-il un peu à l'opération de la session HTTP? Haha.
5) Enfin, définissez un intercepteur SpringMVC pour obtenir les informations utilisateur dans la session correspondante dans l'intercepteur. S'il ne peut pas être obtenu, il passera à l'interface de connexion.
package com.smart.core.shiro; import com.smart.pojo.user; import org.apache.shiro.securityutils; import org.apache.shiro.mgt.securityManager; import org.apache.shiro.subject.subject; import org.slf4j.logger; importation; import; org.slf4j.loggerfactory; import org.springframework.beans.factory.annotation.autowired; import org.springframework.web.servlet.handlerInterceptor; import; javax.servlet.http.httpservletResponse; public class LoginInterceptor implémente handlerInterceptor {private logger logger = loggerfactory.getLogger (loginInterceptor.class); @Autowired Private SecurityManager SM; @Override public boolean prehandle (httpServletRequest httpservletRequest, httpservletResponse httpservletResponse, objet o) exception {logger.info ("entrez le loginInterceptor ..."); HttpServLetRequest request = httpServleRequest; HttpServletResponse Response = httpServletResponse; Logger.info ("request uri ===>" + request.getRequeSturi ()); // S'il s'agit d'une demande de page de connexion, elle ne sera pas interceptée, sinon elle tombera dans une boucle morte if (request.getRequesturi (). Contient ("LoginPage") || request.getRequesturi (). Contise ("userLogin")) {return true; } else {SecurityUtils.SetSecurityManager (SM); Sujet currentUser = SecurityUtils.getSubject (); Objet obj = currentUser.getSession (). GetAttribute ("login_user"); if (obj == null) {réponse.sendRedirect ("http: // localhost: 8080 / user / loginpage"); retourne false; } else {utilisateur utilisateur = (utilisateur) obj; if (user == null || user.getName () == null) {réponse.sendRedirect ("http: // localhost: 8080 / user / loginpage"); retourne false; } else {return true; }}}} @Override public void Posthandle (httpServletRequest httpservletRequest, httpservletResponse httpservletResponse, objet o, modelView ModelAndView) lance une exception {} @Override public void après complétion (httpserSerquest httServletReQue httpservletResponse, objet o, exception e) lève une exception {}}C'est essentiellement ici. Si vous accédez directement aux informations sur la page d'accueil, il passera automatiquement à la page de connexion.
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.