Shiro
Shiro é um projeto de código aberto do Apache, chamamos de Apache Shiro. É uma estrutura de segurança muito fácil de usar com projetos Java, fornecendo autenticação, autorização, criptografia e gerenciamento de sessões. Como a segurança da primavera, é uma estrutura de segurança de permissão. No entanto, em comparação com a segurança da primavera, a Shiro usa um método de autorização relativamente simples, fácil de entender e fácil de usar. Shiro é uma estrutura leve. É muito mais simples que a segurança e não é tão complicado quanto a segurança. Para apresentações mais detalhadas, você pode basicamente aprender com seu site oficial (http://shiro.apache.org/) que ele fornece principalmente as seguintes funções:
(1) Autenticação (autenticação)
(2) Autorização (autorização)
(3) Gerenciamento de sessão (gerenciamento de sessão)
(4) criptografia (criptografia)
Primeiro de tudo, o serviço de autenticação, ou seja, através dela, você pode concluir a autenticação de identidade, permitindo que ela determine se o usuário é um membro real.
Em segundo lugar, o serviço autorizado, para ser franco, é o serviço "controle de acesso", ou seja, que ela identifique quais permissões o usuário tem. Para ser franco, é dar a ele quais permissões de operação julgando qual é o papel do usuário.
Depois, há o serviço de gerenciamento de sessão. No momento, uma estrutura independente de gerenciamento de sessões é diferente da sessão HTTP com a qual estamos familiarizados.
Finalmente, ela também fornece serviços de criptografia (criptografia), encapsulando muitos algoritmos criptográficos.
Hoje, não vou dizer tudo sobre isso e foco em sua função de gerenciamento de conversas. De fato, isso é algo que quase todas as redes devem estar envolvidas.
Antes de falar sobre o serviço de gerenciamento de sessões da Shiro, vamos revisar como fizemos o gerenciamento de sessão anterior.
1. No começo, usamos diretamente o mecanismo de sessão HTTP do servidor da Web. Ou seja, se o usuário entrar pela primeira vez, o contêiner da Web criará uma sessão para a solicitação e, em seguida, armazenará a sessão. Passando o SessionID correspondente como um cookie para o cliente.
Se o cliente enviar uma solicitação para este servidor novamente, o SessionID será trazido automaticamente. Em seguida, o servidor da Web determinará se a sessão ainda está na memória com base no SessionID trazida pelo cliente (a sessão tem um tempo de expiração e pode ser configurado no arquivo web.xml). Se a sessão correspondente não puder ser encontrada, significa que o tempo de expiração da sessão foi passado. No momento, o servidor da web criará uma sessão para ela novamente e depois passará o novo SessionID para o cliente como antes.
Portanto, podemos usar esse mecanismo para gerenciar a sessão de login do usuário no programa. Por exemplo, depois que o primeiro login do usuário for bem -sucedido, armazenamos as informações básicas do usuário na sessão (por exemplo: session.setAttribute("user", "userInfo") ). Na próxima vez que o usuário visitar novamente, obtemos as informações do usuário na sessão atual com base nas informações do usuário
( session.getAttribute("user") ) para determinar se o usuário expirou. Se não puder ser obtido, o usuário será solicitado a fazer login novamente.
2. O segundo método é transferir o local onde as informações são armazenadas em mídia de terceiros, como cache, memecache ou redis. Este método é adotado principalmente devido ao surgimento de sistemas distribuídos.
Nesse caso, precisamos gerar o SessionID nós mesmos. Geralmente, usaremos um prefixo definido ( user:login:token ) e adicionaremos UserID ou Timestamp. Em seguida, usaremos este SessionID como a chave do cache, e as informações do usuário como valor, e armazenamos no cache e definirá o tempo de invalidação:
jedisclient.set (tokenkey, jsonutil.tojSonstring (userInfo)); jedisclient.expire (tokenkey, token_lose_seconds);
Também precisamos passar o tokenkey gerado para o cliente através de cookies: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);
Dessa forma, quando o usuário visita a próxima vez (define um interceptador), podemos tirar o tokenkey correspondente do cookie e depois usar esse tokenkey para ir ao cache para recuperar o valor correspondente. Se não puder ser obtido, significa que a chave expirou e o usuário é solicitado a fazer login novamente.
Nota: Tokenkey é importante, é o hub que conecta o lado do cache e o cliente.
3. O último é o nosso método Shiro, e a idéia é semelhante. O código é bastante simples, então vou fazer o upload do código:
1) Crie um novo arquivo ApplicationContext-shiro.xml:
<? xml versão = "1.0" coding = "utf-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: context = "http://wwwxt.springframework.org/schema =" http://wwwx. xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema 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"> <propriedade name = "SecurityManager" ref = "SecurityManager"> </propriedade> <propriedade name = "Loginurl" value = "/loginpage"> </property> <propriedades name = "unauthorizedurl" value = "/páginas/uNauthion.jsp"/> <nome da "" shotChinNefinon/"/Pages/uNAuthition =)/)/james) anon </value> </propriedade> </bean> <ipean> <propriedade name = "staticmethod" value = "org.apache.shiro.securityutils.seSecurityManager"> </propriedade> <names = "argumentos" referta "" SecurityManager "> </sonweeous> </bEAN> <Bean id =" ref = "Cachemanager"> </ouse> <propriedade name = "sessionManager" ref = "sessionManager"> </propriedade> </bean> <bean id = "sessionManager"> <names name = "sessionDao" ref = "sessionDao"> </ Bean> // Esta classe precisa ser implementada por ele/<Bebante = "cacheman"
2) Configure o filtro correspondente em web.xml:
<filter> <filter-name> shirofilter </filter-name> <filter-Class> org.springframework.web.filter.delegatingFilterProxy </filter-class> <iit-param> </param-name> TargetFilterLifecycle </param-name> <airvalue> </param-value> <Filter-Name> shirofilter </filter-name> <url-tattern>/*</url-tattern> </filter-mapping>
3) Escreva uma classe de implementação, Herite AbstractSessionDao e implemente o método correspondente.
pacote com.jdd.core.shiro; importação com.smart.core.redis.redismanager; importar org.apache.shiro.session.session; importação org.apache.shiro.session.unkNownsessionException; importar org.apache.shiro.session.mgt.eis.abstractSexcepts; org.springframework.beans.factory.annotation.autowired; importar org.springframework.util.Serializationutils; importar java.io. @Override public void update (sessão) lança desconhecidaSessionException {RedisManager.set (serializationutils.Serialize (session.getId (). Tostring ()), serializationutils.serialize (sessão)); RedisManager.Expire (serializationUtils.Serialize (session.getId (). ToString ()), 60); } @Override public void Delete (sessão de sessão) {RedisManager.del (serializationutils.serialize (session.getId (). Tostring ())); } @Override Public Collection <Session> getActiveSessions () {return new ArrayList <Session> (); } @Override Protected Docreate serializável (sessão de sessão) {// É quando você acessa pela primeira vez, crie sessionID serializável sid = this.GeneratesessionId (Sessão); AtributSessionId (sessão, SID); RedisManager.Set (serializationUtils.Serialize (session.getId (). ToString ()), serializationUtils.Serialize (Session)); RedisManager.Expire (serializationUtils.Serialize (session.getId (). ToString ()), 60); retornar Sid; } @Override Sessão protegida DoreadSession (Serializable Serializable) {// Este método é realmente para ler a sessão através da SessionID. Cada vez que você o lê, o tempo de falha deve ser redefinido byte [] aa = redisManager.get (serializationUtils.Serialize (serializable.toString ())); Sessão session = (sessão) serializationUtils.Deserialize (AA); RedisManager.Set (serializationUtils.Serialize (Serializable.ToString ()), SerializationUtils.Serialize (Sessão)); RedisManager.Expire (serializationUtils.Serialize (Serializable.toString ()), 60); sessão de retorno; }}4) A próxima etapa é obter a sessão de Shiro na lógica após o login bem -sucedido e depois definir as informações do usuário em
pacote com.smart.Controller; importar com.smart.pojo.user; importar com.smart.service.userService; importar org.apache.shiro.securityutils; importache.shiroCache.shiro.mgt.security org.slf4j.loggerFactory; importar org.springframework.beans.factory.annotation.aUtowired; importar org.springframework.steretype.controller; importação org.springframework.ui.model; importação. javax.servlet.http.httpServletRequest; importar javax.servlet.http.httpServletResponse;@controlador@requestmapping ("/user") classe pública UserController {@autowired private Uservice Service; @Autowired Private SecurityManager SM; // injeção de segurança securityManager privado logger) = LoggerFactory.getLogger (userController.class); @RequestMapping (value = "/loginpage") public string loginpage () {return "user/userLogin"; } @RequestMapping (value = "/userLogin", método = requestMethod.post) public string userLogin (@RequestParam (value = "nome") Nome da sequência, @RequestParam (value = "pwd") string pwd, modelo modelo) {logger.info ("enter userLogin ...); Usuário Usuário = UserService.getUserBynameAndPassword (nome, PWD); if (usuário == null) {Logger.info ("Usuário não existe ..."); Model.addattribute ("login_error", "nome de usuário ou erro de senha"); retornar "User/UserLogin"; } SecurityUtils.SetSecurityManager (SM); Assunto CurrentUser = SecurityUtils.getSubject (); currentUser.getSession (). SetAttribute ("login_user", usuário); retornar "redirecionar:/funcionário/list"; }}Obtenha o usuário atual, em Shiro, é o tema, obtenha a sessão correspondente e defina as informações do usuário. Parece um pouco como a operação da sessão HTTP? Haha.
5) Finalmente, defina um interceptador SpringMVC para obter as informações do usuário na sessão correspondente no interceptador. Se não puder ser obtido, ele saltará para a interface de login.
pacote com.smart.core.shiro; importar com.smart.pojo.user; importar org.apache.shiro.securityutils; importar org.apache.shiro.mgt.securityManager; importar org.apache.shiro.sUbject.Subject; importação ou importância; org.springframework.beans.factory.annotation.autowired; importar org.springframework.web.servlet.HandlerInterceptor; importação org.springframework.web.servlet.modelandView; Import Javax.servlet.http.httletlest; javax.servlet.http.httpServletResponse; classe pública LoginInterceptor implementa HandlerInterceptor {private logger logger = LoggerFactory.getLogger (loginIntercept.class); @Autowired Private SecurityManager SM; @Override public boolean prehandle (httpServletRequest httpServletRequest, httpServletResponse httpServletResponse, objeto o) lança a exceção {logger.info ("Digite logininterceptor ..."); HttpServletRequest solicitação = httpServletRequest; HttpServletResponse Response = httpServletResponse; logger.info ("solicitar uri ===>"+request.getRequesturi ()); // Se for uma solicitação para a página de login, ela não será interceptada; caso contrário, ele cairá em um loop morto se (request.getRequesturi (). Contém ("loginpage") || request.getRequesturi (). } else {SecurityUtils.seSecurityManager (SM); Assunto CurrentUser = SecurityUtils.getSubject (); Objeto obj = currentUser.getSession (). GetAttribute ("login_user"); if (obj == null) {Response.sendRedirect ("http: // localhost: 8080/user/loginpage"); retornar falso; } else {usuário usuário = (usuário) obj; if (user == null || user.getName () == null) {Response.sendRedirect ("http: // localhost: 8080/user/loginpage"); retornar falso; } else {return true; } } } } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse HttpServletResponse, objeto o, exceção e) lança a exceção {}}Está basicamente aqui. Se você acessar as informações da página inicial diretamente agora, elas pularão automaticamente para a página de login.
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.