亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

spring整合shiro框架的實現步驟記錄

2024-07-14 08:40:48
字體:
來源:轉載
供稿:網友

shiro

Shiro是Apache下的一個開源項目,我們稱之為Apache Shiro。它是一個很易用與Java項目的的安全框架,提供了認證、授權、加密、會話管理,與spring Security 一樣都是做一個權限的安全框架,但是與Spring Security 相比,在于 Shiro 使用了比較簡單易懂易于使用的授權方式。shiro屬于輕量級框架,相對于security簡單的多,也沒有security那么復雜。更多詳細的介紹可以從它的官網上(http://shiro.apache.org/)基本可以了解到,她主要提供以下功能:

 ?。?)Authentication(認證)

  (2)Authorization(授權)

 ?。?)Session Management(會話管理)

 ?。?)Cryptography (加密)

首先,認證服務,也就是說通過她可以完成身份認證,讓她去判斷用戶是否為真實的會員。

其次,授權服務,說白了就是“訪問控制”服務,也就是讓她來識別用戶擁有哪些權限。再說的白一點,就是通過判斷用戶是什么角色,來賦予他哪些操作權限。

然后,還有會話管理服務, 這時一個獨立的Session管理框架,和我們熟知的Http Session 不太一樣。

最后,她還提供了Cryptography(加密)服務,封裝了很多密碼學的算法。

今天,我就不全說了,重點說下她的 會話管理功能, 其實這個也是幾乎所有的web應該都會涉及到的。

在說shiro的會話管理服務前,先回顧下之前的會話管理我們是怎么做的。

1、最初我們是直接用的web服務器的 Http Session的機制, 也就是用戶第一次進來的話,web容器會為這個請求創建一個session,然后把這個session存儲起來,通過將對應的sessionId,作為cookie傳給客戶端,

如果客戶端再次向這個服務器發送請求的話,會自動將這個sessionId帶過來, 然后web服務器會根據客戶端帶過來的 sessionId, 判斷其對于的session 是否還存在于內存中(session是有過期時間的,可以在web.xml文件里面配置),如果找不到對應的session了,說明已經過了session失效時間,這時web服務器會再次為它創建一個session,然后和之前一樣,將這個新的sessionId傳給客戶端。

因此,我們可以通過這種機制,在程序里管理用戶的登錄會話,比如我們在用戶第一次登錄成功后,將用戶的基本信息存儲在session里(比如:session.setAttribute("user", "userInfo") ),下次用戶再次訪問的時候,我們根據獲取當前session里的user信息

session.getAttribute("user") ),來判斷用戶是否過期,如果獲取不到,那么提示用戶重新登錄。

2、第二種方式,就是我們將存儲信息的地方轉移到第三方介質中,比如緩存里,memecache或者Redis都可以,這種方式主要是因為分布式系統的出現而采用的。

這種情況下,就需要我們自己生成sessionId了,一般我們會用一個定義好的前綴(user:login:token)再加上userid,或者時間戳都可以。 然后我們會將這個sessionId作為緩存的key, 用戶的信息作為value,存入緩存中,并設置失效時間:

  jedisClient.set(tokenKey, JsonUtil.toJSONString(userInfo));  jedisClient.expire(tokenKey, TOKEN_LOSE_SECONDS);

我們還要將生成的這個tokenKey通過cookie傳到客戶端: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);

這樣,我們在用戶下次訪問的時候(定義一個攔截器),就可以從cookie里取出對應的tokenKey,然后用這個tokenKey去到緩存里取相應的值,如果獲取不到,說明這個key已經失效了,提示用戶重新登錄。

注: tokenKey 很重要,她是連接緩存端和客戶端的樞紐。

3、最后一種就是我們shiro方式了,思路也類似,代碼挺簡單的,那我就直接上代碼吧:

1)、新建一個 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/aop" xmlns:tx="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/context/spring-context-4.0.xsd 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.xsd"> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"></property> <property name="loginUrl" value="/loginPage"></property> <property name="unauthorizedUrl" value="/pages/unauthorized.jsp"/> <property name="filterChainDefinitions"> <value> /jcaptcha* = anon /logout = anon </value> </property> </bean> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"></property> <property name="arguments" ref="securityManager"></property> </bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="cacheManager" ref="cacheManager"></property> <property name="sessionManager" ref="sessionManager"></property> </bean> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="sessionDAO" ref="sessionDAO"></property> </bean> <bean id="sessionDAO" class="com.smart.core.shiro.MySessionDAO"></bean>  //這個類是需要自己實現的 <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean></beans>

2)、在web.xml 里配置相應的 filter:

<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param>  <param-name>targetFilterLifecycle</param-name>  <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

3)寫一個實現類,繼承 AbstractSessionDAO,實現相應的方法。

package com.jdd.core.shiro;import com.smart.core.redis.RedisManager;import org.apache.shiro.session.Session;import org.apache.shiro.session.UnknownSessionException;import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.SerializationUtils;import java.io.*;import java.util.ArrayList;import java.util.Collection;public class MySessionDAO extends AbstractSessionDAO { @Autowired private RedisManager redisManager; @Override public void update(Session session) throws UnknownSessionException { 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) {    //這就是第一次訪問的時候,創建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); return sid; } @Override protected Session doReadSession(Serializable serializable) {  //這個方法其實就是通過sessionId讀取session,每讀一次,都要重新設置失效時間 byte[] aa = redisManager.get(SerializationUtils.serialize(serializable.toString())); Session session = (Session) SerializationUtils.deserialize(aa); redisManager.set(SerializationUtils.serialize(serializable.toString()), SerializationUtils.serialize(session)); redisManager.expire(SerializationUtils.serialize(serializable.toString()), 60); return session; } }

4)下一步,我就是要在登錄成功之后的邏輯里,獲取到shiro 的session,然后將用戶信息設置進去

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;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@Controller@RequestMapping("/user")public class UserController { @Autowired private UserService userService; @Autowired private SecurityManager sm;  //注入SecurityManager private Logger logger = LoggerFactory.getLogger(UserController.class); @RequestMapping(value = "/loginPage") public String loginPage(){ return "user/userLogin"; } @RequestMapping(value = "/userLogin", method = RequestMethod.POST) public String userLogin(@RequestParam(value="name") String name, @RequestParam(value="pwd") String pwd, Model model){ logger.info("enter userLogin..."); User user = userService.getUserByNameAndPassword(name, pwd); if(user == null){  logger.info("user is not exist...");  model.addAttribute("login_error", "用戶名或密碼錯誤");  return "user/userLogin"; } SecurityUtils.setSecurityManager(sm); Subject currentUser = SecurityUtils.getSubject();     currentUser.getSession().setAttribute("LOGIN_USER", user);  return "redirect:/employee/list"; }}

獲取當前用戶,在shiro里是主題,然后獲取對應的session,并將用戶信息設置進去,是不是感覺有點像Http session的操作的樣子,哈哈。

5)、最后,定義一個springmvc 的攔截器,在攔截器里獲取相應的session里的而用戶信息,如果獲取不到,則跳轉到登錄界面。

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;import org.slf4j.LoggerFactory;import 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 implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class); @Autowired private SecurityManager sm; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { logger.info("enter LoginInterceptor..."); HttpServletRequest request = httpServletRequest; HttpServletResponse response = httpServletResponse; logger.info("request uri===>"+request.getRequestURI());      //如果是登錄頁面的請求,則不攔截,否則會陷入死循環 if(request.getRequestURI().contains("loginPage") || request.getRequestURI().contains("userLogin")){  return true; }else{  SecurityUtils.setSecurityManager(sm);  Subject currentUser = SecurityUtils.getSubject();  Object obj = currentUser.getSession().getAttribute("LOGIN_USER");  if(obj==null){  response.sendRedirect("http://localhost:8080/user/loginPage");  return false;  }else{  User user = (User)obj;  if(user==null || user.getName()==null){   response.sendRedirect("http://localhost:8080/user/loginPage");   return false;  }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, Object o, Exception e) throws Exception { }}

到這里就基本結束了,如果你現在直接訪問主頁信息的話,它會自動跳到登錄頁面。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线电影av不卡网址| 久久影视免费观看| 国产69精品久久久久9| 懂色aⅴ精品一区二区三区蜜月| 欧美大片在线影院| 精品欧美aⅴ在线网站| 久久久久久亚洲精品不卡| 久久久免费观看视频| 亚洲精品综合久久中文字幕| 亚洲精品在线91| 国产ts一区二区| 中文字幕日韩av综合精品| 丰满岳妇乱一区二区三区| 欧美视频裸体精品| 日本精品免费观看| 欧美精品国产精品日韩精品| 日韩av在线高清| 日韩精品极品在线观看播放免费视频| 成人午夜两性视频| 久久久精品在线观看| 亚洲的天堂在线中文字幕| 国产精品免费视频xxxx| xxx成人少妇69| 亚洲国产天堂久久综合网| 国产日韩在线看片| 亚洲福利在线视频| 色偷偷av一区二区三区| 国产精品美乳一区二区免费| 欧美自拍大量在线观看| 国色天香2019中文字幕在线观看| 国产91对白在线播放| 国产精品免费一区二区三区都可以| 91久久中文字幕| 亚洲男人天堂网站| 欧美成人中文字幕在线| 国产午夜精品一区理论片飘花| 久久亚洲精品中文字幕冲田杏梨| 国产精品欧美日韩一区二区| 成人a视频在线观看| 亚洲深夜福利网站| 成人福利免费观看| 亚洲精品免费在线视频| 日韩成人激情影院| 国产亚洲欧美日韩精品| 国产精品一区二区电影| 美女啪啪无遮挡免费久久网站| 国产深夜精品福利| 日韩精品视频在线观看网址| 国产日韩在线精品av| 亚洲成人精品久久| 亚洲欧美日韩国产中文| 91久热免费在线视频| 久久电影一区二区| 色婷婷av一区二区三区久久| 欧美精品性视频| 国产91ⅴ在线精品免费观看| 97在线视频免费播放| 亚洲色图偷窥自拍| 国产一区二区三区日韩欧美| 欧美老女人在线视频| 国产成人在线亚洲欧美| 国产精品视频一区二区三区四| 欧美日韩一区二区精品| 91人人爽人人爽人人精88v| 91视频国产一区| 亚洲美女精品久久| 久久精品影视伊人网| 亚洲美女av网站| 亚洲激情国产精品| 国产999精品| 91欧美视频网站| 欧美激情综合亚洲一二区| 精品一区二区三区电影| 51ⅴ精品国产91久久久久久| 亚洲国产精品美女| 国产精品久久久久7777婷婷| 亚洲最新av网址| 一本一道久久a久久精品逆3p| 亚洲国产成人精品电影| 欧美激情免费在线| 国产经典一区二区| 91成人在线播放| 国产精品91久久久久久| 4438全国亚洲精品在线观看视频| 91在线视频导航| 亚洲国产精品视频在线观看| 亚洲伊人久久综合| 亚洲成人黄色网址| 国产欧美精品xxxx另类| 色悠悠国产精品| 色哟哟入口国产精品| 亚洲人午夜精品| 国产成人av在线播放| 国产精品一区二区三区在线播放| 亚洲欧美日韩天堂一区二区| 国产精品久久在线观看| 亚洲精品v欧美精品v日韩精品| 91九色蝌蚪国产| 欧美日韩高清区| 色琪琪综合男人的天堂aⅴ视频| 久久全球大尺度高清视频| 欧美精品在线观看91| 亚洲成**性毛茸茸| 青草热久免费精品视频| 精品日本美女福利在线观看| 午夜精品久久久久久久白皮肤| 亚洲爱爱爱爱爱| 亚洲精品成a人在线观看| 日韩精品小视频| zzijzzij亚洲日本成熟少妇| 视频在线观看一区二区| 欧美综合激情网| 色先锋久久影院av| 亚洲精品国产欧美| 成人免费高清完整版在线观看| 国产精品99久久久久久久久久久久| 国产精品视频26uuu| 久久久久久久一区二区| 久久99久国产精品黄毛片入口| 国产精品久久久久久久久久久新郎| 日韩高清电影好看的电视剧电影| 成人有码视频在线播放| 国产精品视频自在线| 色老头一区二区三区| 欧美最猛性xxxxx亚洲精品| 久久福利网址导航| 色无极影院亚洲| 久久精品国产清自在天天线| 91精品视频在线| 亚洲韩国欧洲国产日产av| 欧美成人午夜剧场免费观看| 日韩高清人体午夜| 欧美午夜精品伦理| 91久久久久久久| 日韩欧美在线播放| 欧美性猛交xxxx乱大交| 国产精品欧美日韩一区二区| 久久全国免费视频| 亚洲18私人小影院| 久久在精品线影院精品国产| 中文字幕日韩专区| 中文字幕亚洲一区在线观看| 国产精品久久久久久久久粉嫩av| 国产日韩欧美成人| 日韩**中文字幕毛片| 亚洲精品久久久久久久久久久久| 久久琪琪电影院| 中文在线资源观看视频网站免费不卡| 久久亚洲精品国产亚洲老地址| 亚洲免费人成在线视频观看| 久久久久国产精品www| 国产美女精品视频| 国产精品亚洲视频在线观看| 日韩不卡在线观看| 亚洲精品资源在线| 欧美激情精品久久久久久| 精品国产鲁一鲁一区二区张丽| 中文国产成人精品久久一| 日韩在线视频一区| 亚洲精品电影久久久| 欧美激情免费观看| 日韩国产欧美精品一区二区三区| 777午夜精品福利在线观看| 欧洲美女7788成人免费视频|