Shiro 使用

Shiro Demo 準備工作

運行前申明

  1. 請看完本頁面的所有細節,對你掌握這個項目來說很重要,別一上來就搞,你不爽,我也不爽。
  2. 本項目需要一定的Java功底,需要對SpringMvcMybatis,有基本的瞭解,其次對Redis有了解和使用更佳。
  3. 本項目理論上,只需要一個Redis,然後一個Mysql和一個有Maven環境的開發工具即可運行起來。
  4. 對Reids沒有了解,請看這裏:對Redis的理解,Redis是什麼,Redis和Memcache誰快?

運行步驟

  1. 從 Github 下載源碼(不定期更新和修復BUG),導入到EclipseMyEclipesIdea類似開發工具。
  2. 解決編譯錯誤,修改JDK1.7以上(請勿使用工具自帶JDK)。
  3. Mysql數據庫中創建一個數據庫,庫名隨便。
  4. 從項目/init/sql/下,先執行tables.sql創建表,再運行init.data.sql插入初始化數據。
  5. 再修改配置jdbc.properties把數據庫鏈接改成您的。
  6. 安裝Redis服務,如果您沒用過,或者沒安裝,請看這裏==>Redis 安裝,以及注意事項都在裏面有說明。Redis啓動報錯請看這裏:Please see the documentation included with the binary distributions for more details on the --maxheap flag.
  7. 安裝完畢後,修改配置:spring-cache.xml,如果是本地,無序修改,啓動Redis,如對Redis不瞭解的同學,建議別設置密碼。
  8. 運行項目,如果還有錯誤請參考異常信息,並解決,如果實在不能解決,請加QQ羣交流,羣需要付費5元,加羣請看右側菜單。
  9. 項目帳號和線上Demo一致:管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用 sojson

線上Demo說明

  1. Demo已經部署到線上,地址是:http://shiro.itboy.net
  2. 管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用 sojson
  3. 你可以註冊自己的帳號,然後用管理員賦權限給你自己的帳號,但是,每20分鐘會把數據初始化一次。建議自己下載源碼,讓Demo跑起來,然後跑的更快,有問題加羣解決。

Shiro Demo 源碼下載

Shiro Demo 非Maven項目依賴包下載:點我下載

Github 0.1版本下載:https://github.com/baichengzhou/SpringMVC-Mybatis-shiro,(請下載0.2版本)

Github 0.2版本下載:https://github.com/baichengzhou/SpringMVC-Mybatis-Shiro-redis-0.2

Shiro Demo 0.2版本介紹:https://www.sojson.com/blog/165.html

Shiro Demo 0.2版本主要解決的問題爲0.1版本出現的問題和BUG。

Shiro Demo 0.2版本爲Shiro Demo 0.1的升級版本

PS:請選用0.2版本,這樣你遇到的問題會比較少。

升級內容:

  1. 修復了些許BUG,優化了語法。
  2. 0.1版本限制較多,比如要部署到Tomcat Root下才能正常運行,就是用http://localhost:8080方式訪問。
  3. 0.2版本可以採用目錄訪問,如:http://localhost:8080/shiro.demo/,默認項目名稱爲/shiro.demo/

Shiro 簡介

Apache Shiro 是 Java  的一個安全框架。我們經常看到它被拿來和 Spring   Security  來對比。大部分人認爲 Shiro   Security  要簡單。我的觀點贊成一半一半吧。

首先 Shiro  確實和 Security  是同類型的框架,主要用來做安全,也就是我們俗稱的權限校驗(控制)。居多人對 Shiro  的定義爲好入門。

我選型爲 Shiro  ,主要的原因擴展太easy了,而且我要的功能它都有。

本教程開發環境

本教程Jar包管理是 Maven  ,所以如果是 Maven  項目下載Demo後可以直接使用,如果是普通的Java Web項目,那麼請在下面下載所有依賴包。

本教程開發工具是Myecilpse8.5

本教程編碼格式爲UTF-8

本教程JDK爲1.7,請勿使用自帶工具JDK。

本教程Mysql爲5.3版本是以上。

Redis 版本隨意。

本教程Spring版本爲4.2.5

前端頁面採用Bootstrap 3.2

本教程包含的內容

  1. SSM(SpringMVC + Spring + Mybatis)框架的增刪改查(含分頁),所以如果框架小白也是可以看看的。
  2. View層主要是Freemarker,但是爲了考慮到好多人還使用的是JSP,也有一個頁面是用JSP實現的,並且框架支持Freemarker 和 JSPView展示(優先找Freemarker)。
  3. Shiro + Redis 的集成,也提供Ehcache的依賴Jar。
  4. Shiro 初始權限動態加載。
  5. Shiro 自定義權限校驗Filter定義,及功能實現。
  6. Shiro Ajax請求權限不滿足,攔截後解決方案。
  7. Shiro Freemarker標籤使用。
  8. Shiro JSP標籤使用。
  9. Shiro 登錄後跳轉到最後一個訪問的頁面。
  10. 用戶禁止登錄Demo
  11. 在線顯示,在線用戶管理(踢出登錄)。
  12. 登錄註冊密碼加密傳輸Demo(詳細請見下面講解)。
  13. 密碼修改。
  14. 用戶個人中心。
  15. 權限的增刪改查。
  16. 角色的增刪改查。
  17. 權限->角色->用戶之間的關係維護。
  18. 管理員權限的自動添加(當有一個權限創建,自動添加到管理員角色下,保證管理員是最大權限)。
  19. Spring定時任務數據化數據。
  20. 集成多種驗證碼(包括動態的gif驗證碼哦)。
  21. 一個帳號多處登錄限制,踢出用戶。
  22. 後續會陸陸續續升級... ...

一、SSM(SpringMVC + Mybatis)框架的增刪改查(含分頁)

本教程是SSM(SpringMVC + Spring + Mybatis + Freemarker + JSP) + Shiro + Redis 做的整體Demo,其他框架需要自己自行解決,所以不做其他框架的講解,其實是大同小異。

Controller ==> Service(事務控制層) ==> Dao ==> SqlMapper ==> Mysql

二、View層 Freemarker,JSP

通用View層配置在spring-mvc.xml中的以【通用試圖解析器】註釋標註的區間配置。

三、Shiro + Redis 的集成,也提供Ehcache的依賴Jar。

Redis 緩存配置主要在spring-cache.xml中。對應的所有Cache 相關 Java  代碼在package:com.sojson.core.shiro.cache

四、Shiro 初始權限動態加載。

我們一般是這麼加載的。在spring-shiro.xml中配置

 


 
  1. <property name="filterChainDefinitions" >
  2. <value>
  3. /** = anon
  4. /page/login.jsp = anon
  5. /page/register/* = anon
  6. /page/index.jsp = authc
  7. /page/addItem* = authc,roles[數據管理員]
  8. /page/file* = authc,roleOR[普通用戶,數據管理員]
  9. /page/listItems* = authc,roleOR[數據管理員,普通用戶]
  10. /page/showItem* = authc,roleOR[數據管理員,普通用戶]
  11. /page/updateItem*=authc,roles[數據管理員]
  12. </value>
  13. </property>

 

本教程採用動態加載,你可以從數據庫裏讀取然後拼接成shiro要的數據。

 

 


 
  1. <property name="filterChainDefinitions" value="#\{shiroManager.loadFilterChainDefinitions()\}"/>

 

配置文件方式加載詳細講解:https://www.sojson.com/blog/148.html

五、Shiro 自定義權限校驗Filter定義,及功能實現。

Shiro Filter在package:com.sojson.core.shiro.filter,具體配置在spring-shiro.xml中。定義了5個攔截器,具體功能看代碼以及代碼註釋。

 


 
  1. <bean id="shiroManager" class="com.sojson.core.shiro.service.impl.ShiroManagerImpl"/>
  2. <bean id="login" class="com.sojson.core.shiro.filter.LoginFilter"/>
  3. <bean id="role" class="com.sojson.core.shiro.filter.RoleFilter"/>
  4. <bean id="permission" class="com.sojson.core.shiro.filter.PermissionFilter"/>
  5. <bean id="simple" class="com.sojson.core.shiro.filter.SimpleAuthFilter"/>

 
  1. <property name="filters">
  2. <util:map>
  3. <entry key="login" value-ref="login"></entry>
  4. <entry key="role" value-ref="role"></entry>
  5. <entry key="simple" value-ref="simple"></entry>
  6. <entry key="permission" value-ref="permission"></entry>
  7. </util:map>
  8. </property>

 

六、Shiro Ajax請求權限不滿足,攔截後解決方案。

這裏有一個前提,我們知道Ajax不能做頁面redirectforward跳轉,所以Ajax請求假如沒登錄,那麼這個請求給用戶的感覺就是沒有任何反應,而用戶又不知道用戶已經退出了。解決代碼如下:

 


 
  1. //Java代碼,判斷如果是Ajax請求,然後並且沒登錄,那麼就給予返回JSON,login_status = 300,message = 當前用戶沒有登錄!
  2. if (ShiroFilterUtils.isAjax(request)) {// ajax請求
  3. Map<String,String> resultMap = new HashMap<String, String>();
  4. LoggerUtils.debug(getClass(), "當前用戶沒有登錄,並且是Ajax請求!");
  5. resultMap.put("login_status", "300");
  6. resultMap.put("message", "\u5F53\u524D\u7528\u6237\u6CA1\u6709\u767B\u5F55\uFF01");//當前用戶沒有登錄!
  7. ShiroFilterUtils.out(response, resultMap);
  8. }

 

 


 
  1. //前端代碼
  2. if(result.login_status == 300){
  3. layer.msg(result.message);//當前用戶沒有登錄!
  4. }

 

七、Shiro Freemarker標籤使用。

Freemarker使用Shiro 標籤的介紹:https://www.sojson.com/blog/143.html

八、Shiro JSP標籤使用。

JSP使用Shiro 標籤的介紹:https://www.sojson.com/blog/144.html

九、Shiro 登錄後跳轉到最後一個訪問的頁面。

 Java  中就可以這樣獲取上一個地址:

 


 
  1. //上一個瀏覽的非Ajax的地址,在登錄後,取得地址,如果不爲null,那麼就跳轉過去。
  2. String url = (String) request.getAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE);
  3. //shiro也有他的方法。詳細看下面。

 

如果需要保存登錄之前的Request信息,那麼需要在Login攔截的Filter中先保存:

 


 
  1. @Override
  2. protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
  3. throws Exception {
  4. //保存Request和Response,登錄後可以取到
  5. saveRequestAndRedirectToLogin(request, response);
  6. return Boolean.FALSE ;
  7. }
  8. //登錄後,取到之前的Request中的一些信息。
  9. SavedRequest saveRequest = WebUtils.getSavedRequest(request);
  10. saveRequest.getMethod();//之前的請求方法
  11. saveRequest.getQueryString();//之前請求的條件
  12. saveRequest.getRequestURI();//之前請求的路徑
  13. saveRequest.getRequestUrl();//之前請求的全路徑

 

十、用戶禁止登錄Demo

這個功能其實是一個改變用戶數據庫表裏的一個字段,本Demo中:1:有效,0:禁止登錄

然後踢出用戶登錄狀態。代碼詳細請查看CustomSessionManager.java類的forbidUserById(Long id, Long status)方法。

而再次登錄的話,需要再登錄,而登錄的地方限制了用戶狀態爲(0:禁止登錄)的用戶登錄。


 
  1. /**
  2. * 查詢要禁用的用戶是否在線。
  3. * @param id 用戶ID
  4. * @param status 用戶狀態
  5. */
  6. public void forbidUserById(Long id, Long status) {
  7. //獲取所有在線用戶
  8. for(UserOnlineBo bo : getAllUser()){
  9. Long userId = bo.getId();
  10. //匹配用戶ID
  11. if(userId.equals(id)){
  12. //獲取用戶Session
  13. Session session = shiroSessionRepository.getSession(bo.getSessionId());
  14. //標記用戶Session
  15. SessionStatus sessionStatus = (SessionStatus) session.getAttribute(SESSION_STATUS);
  16. //是否踢出 true:有效,false:踢出。
  17. sessionStatus.setOnlineStatus(status.intValue() == 1);
  18. //更新Session
  19. customShiroSessionDAO.update(session);
  20. }
  21. }
  22. }

十一、在線顯示,在線用戶管理(踢出登錄)

上面的功能依賴這個功能。從Redis中獲取所有有效的Session


 
  1. /**
  2. * 獲取所有的有效Session用戶
  3. * @return
  4. */
  5. public List getAllUser() {
  6. //獲取所有session
  7. Collection sessions = customShiroSessionDAO.getActiveSessions();
  8. List list = new ArrayList();
  9.  
  10. for (Session session : sessions) {
  11. UserOnlineBo bo = getSessionBo(session);
  12. if(null != bo){
  13. list.add(bo);
  14. }
  15. }
  16. return list;
  17. }

踢出後,不能直接退出,要不然用戶感覺莫名其妙。所有增加了一個Filter。SimpleAuthFilter.java如果標記爲踢出,會提示用戶。具體查看源碼以及配合項目的使用。

十二、登錄註冊密碼加密傳輸

這個地方好多人糾結的。比如密碼過於簡單,即使加密後也能破解。如我們把密碼:123456,加密後就是:e10adc3949ba59abbe56e057f20f883e

這個很容易被識別,導致不安全,現在市面上的MD5破解其實就是把常用的數字,字母進行先加密,然後對比,美其名曰破解MD5。

那怎麼能讓用戶即使使用很簡單的密碼,也發現不了?

本Demo的實現方式是:MD5(登錄帳號 + “固定值” + 密碼),把這個作爲密碼,這樣,基本是不可能猜的出來。

 


 
  1. //Java代碼。UserManager.md5Pswd(UUser user);
  2. /**
  3. * 加工密碼,和登錄一致。
  4. * @param user
  5. * @return
  6. */
  7. public static UUser md5Pswd(UUser user){
  8. //密碼爲 email + '#' + pswd,然後MD5
  9. user.setPswd(md5Pswd(user.getEmail(),user.getPswd()));
  10. return user;
  11. }
  12. /**
  13. * 字符串返回值
  14. * @param email
  15. * @param pswd
  16. * @return
  17. */
  18. public static String md5Pswd(String email ,String pswd){
  19. pswd = String.format("%s#%s", email,pswd);
  20. pswd = MathUtil.getMD5(pswd);
  21. return pswd;
  22. }

 
  1. //JS代碼
  2. var pswd = MD5(username +"#" + password);

 

十三、密碼修改

不講了,和上面原理一致,然後具體看Demo。

十四、用戶個人中心

包含的功能有[個人資料,資料修改,密碼修改,我的權限],具體看Demo。

十五、權限的增刪改查。

Demo的設計是遵循RBAC3的思想。https://www.sojson.com/blog/142.html

RBAC個人理解介紹:https://www.sojson.com/blog/141.html

 

轉載地址: https://www.sojson.com/shiro

http://www.cnblogs.com/learnhow/p/5694876.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章