Shiro
Shiro es un proyecto de código abierto en Apache, lo llamamos Apache Shiro. Es un marco de seguridad muy fácil de usar con proyectos Java, que proporciona autenticación, autorización, cifrado y gestión de sesiones. Al igual que Spring Security, es un marco de seguridad de permiso. Sin embargo, en comparación con la seguridad de la primavera, Shiro utiliza un método de autorización relativamente simple, fácil de entender y fácil de usar. Shiro es un marco liviano. Es mucho más simple que la seguridad y no es tan complicado como la seguridad. Para presentaciones más detalladas, básicamente puede aprender de su sitio web oficial (http://shiro.apache.org/) que proporciona principalmente las siguientes funciones:
(1) autenticación (autenticación)
(2) Autorización (autorización)
(3) Gestión de sesiones (gestión de sesiones)
(4) criptografía (cifrado)
En primer lugar, el servicio de autenticación, es decir, a través de ella, puede completar la autenticación de identidad, lo que le permite determinar si el usuario es un miembro real.
En segundo lugar, el servicio autorizado, para decirlo sin rodeos, es el servicio de "control de acceso", es decir, dejarla identificar qué permisos tiene el usuario. Para decirlo sin rodeos, es darle qué permisos de operación juzgando qué papel es el usuario.
Luego, está el servicio de gestión de sesiones. En este momento, un marco de gestión de sesión independiente es diferente de la sesión HTTP con la que estamos familiarizados.
Finalmente, ella también proporciona servicios de criptografía (cifrado), encapsulando muchos algoritmos criptográficos.
Hoy, no diré todo al respecto y me concentraré en la función de gestión de su conversación. De hecho, esto es algo que casi todas las redes deberían estar involucradas.
Antes de hablar sobre el servicio de gestión de sesiones de Shiro, revisemos cómo hicimos la gestión de sesión anterior.
1. Al principio utilizamos directamente el mecanismo de sesión HTTP del servidor web. Es decir, si el usuario viene por primera vez, el contenedor web creará una sesión para la solicitud y luego almacenará la sesión. Al pasar la sesión de sesión correspondiente como una cookie para el cliente.
Si el cliente envía una solicitud a este servidor nuevamente, el SessionID se traerá automáticamente. Luego, el servidor web determinará si la sesión todavía está en la memoria en función del SessionID traído por el cliente (la sesión tiene un tiempo de vencimiento y puede configurarse en el archivo web.xml). Si no se puede encontrar la sesión correspondiente, significa que el tiempo de vencimiento de la sesión ha pasado. En este momento, el servidor web volverá a crear una sesión para ella y luego pasará el nuevo SessionID al cliente como antes.
Por lo tanto, podemos usar este mecanismo para administrar la sesión de inicio de sesión del usuario en el programa. Por ejemplo, después de que el primer inicio de sesión del usuario sea exitoso, almacenamos la información básica del usuario en la sesión (por ejemplo: session.setAttribute("user", "userInfo") ). La próxima vez que el usuario vuelva a visitar, obtenemos la información del usuario en la sesión actual en función de la información del usuario
( session.getAttribute("user") ) para determinar si el usuario ha expirado. Si no se puede obtener, se le pedirá al usuario que vuelva a iniciar sesión.
2. El segundo método es transferir el lugar donde la información se almacena a los medios de comunicación de terceros, como caché, memecache o redis. Este método se adopta principalmente debido a la aparición de sistemas distribuidos.
En este caso, necesitamos generar la sesión de Session. En general, utilizaremos un prefijo definido ( user:login:token ) y agregaremos ID de usuario o marca de tiempo. Luego usaremos este SessionId como clave de caché, y la información del usuario como valor, y la almacenaremos en el caché y establecerá el tiempo de invalidación:
jedisclient.set (tokenkey, jsonutil.tojsonstring (userInfo)); JedIsclient.EXPIRE (tokenkey, token_lose_seconds);
También necesitamos pasar el tokenkey generado al cliente a través de cookies: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);
De esta manera, cuando el usuario visita la próxima vez (define un interceptor), podemos sacar el tokenkey correspondiente de la cookie, y luego usar este tokenkey para ir al caché para recuperar el valor correspondiente. Si no se puede obtener, significa que la clave ha expirado y se le solicita al usuario que vuelva a iniciar sesión.
Nota: Tokenkey es importante, es el concentrador que conecta el lado de la caché y el cliente.
3. El último es nuestro método Shiro, y la idea es similar. El código es bastante simple, por lo que solo cargaré el código:
1) Cree un nuevo archivo AplicationContext- Shiro.xml:
<? xml versión = "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://wwww.w3.org/2001/xmlschema" xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/contextExt http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org//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.xsd"> <bean id = "shiroFilter"> <Property name = "SecurityManager" ref = "SecurityManager"> </Property> <Property Name = "LoginUrl" valor = "/loginpage"> </Property> <Property Name = "UNAUTHORIEDURL" Value = "/PAGES/UNAUTHORIED.JSPE"/> <Nombre de propiedad = "Filtro de la propiedad =" FilterDefinInTs "> <Vonal> anon </value> </property> </reme> <reme> <propiedad name = "staticMethod" value = "org.apache.shiro.securityUtiliLs.setsecurityManager"> </property> <Property name = "argumentos" ref = "SecurityManager"> </Property> </bean Id = "SecurityManager"> <Property Nombre = "Cachemanger" Ref. <Property Name = "SessionManager" ref = "SessionManager"> </property> </le bean> <bean id = "sessionManager"> <Property name = "sessiondao" ref = "sessiondao"> </bean> // Esta clase necesita ser implementada por sí misma <bean id = "cachemanager"> </bean> </bean>>
2) Configure el filtro correspondiente en Web.xml:
<Sterry> <Sterry-name> shiroFilter </filter-name> <filter-class> org.springframework.web.filter.delegatingFilterProxy </filter-class> <itel-param> <amamname> targetFilterlifecycle </amamname-Name> <Armarr-Value> true </amam-value> <//initil-inyil> </filtro> </filtro> <filter-name> shirofilter </filter-name> <url-pattern>/*</sl-Pattern> </filter-mapping>
3) Escribir una clase de implementación, heredar AbstractSessionDao e implementar el método correspondiente.
paquete com.jdd.core.shiro; import com.smart.core.redis.redismanger; import org.apache.shiro.session.session; import org.apache.shiro.session.unknownsessionexception; import org.apache.shiro.session.mgt.eis.absessiondao; import org.springframework.beans.factory.annotation.aUtowired; import org.springframework.util.serializationUtils; import java.io.*; import java.util.arrayList; import java.util.collection; clase pública mySessiondao extiende los abstractssession {@auTowired private privado privado privado Redismanager; @Override public void Update (sesión Session) lanza FocksessessionException {redismanger.set (serializationUtil.serialize (session.getID (). ToString ()), serializationUtils.serialize (session)); RedIsManager.EXPIRE (SerializationUtils.serialize (session.getID (). toString ()), 60); } @Override public void Delete (sesión de sesión) {redismanger.del (serializationUtil.serialize (session.getId (). ToString ())); } @Override Public Collection <Session> getActivesSesions () {return new ArrayList <session> (); } @Override protegido serializable doCreate (sesión de sesión) {// Esto es cuando accede por primera vez, crea sessionID serializable sid = this.generatessionId (sesión); asignSessionID (sesión, sid); redismanger.set (serializationUtils.serialize (session.getID (). toString ()), serializationUtils.serialize (session)); RedIsManager.EXPIRE (SerializationUtils.serialize (session.getID (). toString ()), 60); regresar a Sid; } @Override Session protegido doreadsession (Serializable Serializable) {// Este método es realmente leer la sesión a través de SessionID. Cada vez que lo lee, el tiempo de falla debe restablecerse el byte [] aa = redismanger.get (serializationUtil.serialize (Serializable.ToString ())); Sesión sesión = (sesión) SerializationUtils.eserialize (aa); redismanger.set (SerializationUtils.serialize (Serializable.ToString ()), SerializationUtils.serialize (sesión)); redismanger.EXPIRE (SerializationUtils.serialize (Serializable.ToString ()), 60); sesión de regreso; }}4) El siguiente paso es obtener la sesión de Shiro en la lógica después de un inicio de sesión exitoso, y luego establecer la información del usuario en
paquete 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; 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.*; import javax.servlet.http.httpservletRequest; import javax.servlet.http.httpservletResponse;@controler@requestmapping ("/user") clase pública UserController {@aUtowired usserService UserSerSerService; @Autowired private SecurityManager SM; // inyect SecurityManager private logger = loggerFactory.getLogger (UserController.class); @RequestMapping (valor = "/loginpage") public String LoginPage () {return "User/UserLogin"; } @RequestMapping (value = "/userLogin", método = requestmethod.post) public string userLogin (@RequestParam (value = "name") Nombre de cadena, @RequestParam (valor = "pwd") String pwd, modelo modelo) {logger.info ("ingresar userLogin ..."); Usuario usuario = UserService.getUserByNameAndPassword (nombre, pwd); if (user == null) {logger.info ("El usuario no es existente ..."); model.addattribute ("Login_error", "Nombre de usuario o error de contraseña"); devolver "User/UserLogin"; } SecurityUtils.SetSecurityManager (SM); Sujeto CurrentUser = SecurityUtils.getSubject (); CurrentUser.getSession (). SetAttribute ("Login_user", usuario); return "redirect:/empleado/list"; }}Obtenga el usuario actual, en Shiro, es el tema, luego obtenga la sesión correspondiente y establezca la información del usuario en ella. ¿Se siente un poco como el funcionamiento de la sesión HTTP? Ja ja.
5) Finalmente, defina un interceptor SpringMVC para obtener la información del usuario en la sesión correspondiente en el interceptor. Si no se puede obtener, saltará a la interfaz de inicio de sesión.
paquete com.smart.core.shiro; import com.smart.pojo.user; import org.apache.shiro.securityutils; import org.apache.shiro.mgt.securityManager; import og.apache.shiro.subject.subject; import org.slf4j.logger; import og.slf4j.LOLLOLLOGTOR org.springframework.beans.factory.annotation.aUtowired; import org.springframework.web.servlet.handlerinterceptor; import org.springframework.web.servlet.modelandview; import javax.servlet.http.httpservletRequest; import; javax.servlet.http.httpservletResponse; public class LoginInterceptor implementa HandlerInterceptor {private Logger logger = loggerFactory.getLogger (loginInterceptor.class); @Autowired private SecurityManager SM; @Override public boolean prehandle (httpservletRequest httpservletRequest, httpservletResponse httpServletResponse, objeto o) arroja excepción {logger.info ("Ingrese LoginInterceptor ..."); HttpservletRequest solicitud = httpservletRequest; Respuesta httpservletResponse = httpservletResponse; logger.info ("Solicitar uri ===>"+request.getRequesturi ()); // Si se trata de una solicitud para la página de inicio de sesión, no se interceptará, de lo contrario caerá en un bucle muerto if (request.getRequesturi (). Contiene ("LoginPage") || request.getRequestUri (). Contiene ("userLogin")) {return true; } else {SecurityUtils.SetSecurityManager (SM); Sujeto CurrentUser = SecurityUtils.getSubject (); Object obj = currentUser.getSession (). GetAttribute ("login_user"); if (obj == null) {Response.sendedirect ("http: // localhost: 8080/user/loginpage"); devolver falso; } else {usuario user = (usuario) obj; if (user == null || user.getName () == null) {Response.sendedirect ("http: // localhost: 8080/user/loginpage"); devolver falso; } else {return true; }}}} @Override public void postthandle (httpServletRequest httPservletRequest, httpServletReSponse httpServletResponse, objeto O, modelandView ModelAndView) lanza la excepción {} @Override public Void AfterCompletion (httpServletRequest htttSewRewe httpservletResponse, objeto o, excepción e) lanza la excepción {}}Básicamente está por aquí. Si accede directamente a la información de la página de inicio, saltará automáticamente a la página de inicio de sesión.
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.