Apache Shiro權限控制實戰,權限控制SpringMVC + Mybatis + Shiro

Demo已經部署到線上,地址是http://shiro.itboy.net
管理員賬號:admin,密碼:sojson.com 若是密碼錯誤,請用sojson。
PS:你能夠註冊本身的賬號,而後用管理員賦權限給你本身的賬號,可是,每20分鐘會把數據初始化一次。建議本身下載源碼,讓Demo跑起來,而後跑的更快,有問題加羣解決。

Shiro Demo 源碼下載

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

Shiro Demo 源碼下載下載:點我(雲端下載)java

Github下載:https://github.com/baichengzhou/SpringMVC-Mybatis-shiromysql

Shiro Demo環境準備

開發工具:EclipseMyEclipseIdea等等。git

依賴第三方:Mysql 5.0以上、Redisgithub

須要的配置:jdbc.properties中配置Mysql的信息、spring-cache.xml配置Redis 配置,若是是默認配置,就不用換,Redis Windows安裝:http://www.sojson.com/blog/110ajax

注意:請不要有端口8080,設置Tomcat端口爲80,而後訪問不要帶項目路徑訪問。就好像生產環節同樣:http://shiro.itboy.net 。redis

Shiro 簡介

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

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

我選型爲 Shiro  ,主要的緣由擴展太easy了,並且我要的功能它都有。數據庫

本教程環境。

本教程Jar包管理是 Maven  ,因此若是是 Maven  項目下載Demo後能夠直接使用,若是是普通的Java Web項目,那麼請在下面下載全部依賴包。

本教程開發工具是Myecilpse8.5

本教程編碼格式爲UTF-8

本教程JDK爲1.7

本教程Spring版本爲4.2.5

前端頁面採用Bootstarp 3.2

本教程包含的內容。

  1. SSM(SpringMVC + Spring + Mybatis)框架的增刪改查(含分頁),因此若是框架小白也是能夠看看的。
  2. View層主要是Freemarker,可是爲了考慮到好多人還使用的是JSP,也有一個頁面是用JSP實現的,而且框架支持FreemarkerJSPView展現(優先找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. 後續會陸陸續續升級... ...

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

本教程是SSM(SpringMVC + Spring + Mybatis + Freemarker + JSP) + Shiro + Redis 作的總體Demo,其餘框架須要本身自行解決,因此不作其餘框架的講解,實際上是大同小異。

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

2、View層 Freemarker,JSP

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

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

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

4、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()\}"/>

 

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

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

Shrio 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>

 

6、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. }

 

7、Shiro Freemarker標籤使用。

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

8、Shiro JSP標籤使用。

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

9、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();//以前請求的全路徑

 

10、用戶禁止登陸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. }

11、在線顯示,在線用戶管理(踢出登陸)。

上面的功能依賴這個功能。從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若是標記爲踢出,會提示用戶。具體查看源碼以及配合項目的使用。

12、登陸註冊密碼加密傳輸。

這個地方好多人糾結的。好比密碼過於簡單,即便加密後也能破解。如咱們把密碼: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);

 

十3、密碼修改。

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

十4、用戶我的中心。

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

十5、權限的增刪改查。

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

RBAC我的理解介紹:http://www.sojson.com/blog/141

具體實現看Demo。

十6、角色的增刪改查。

 

十7、權限->角色->用戶之間的關係維護。

把權限賦給角色。

把角色賦給用戶。

十8、管理員權限的自動添加

這裏每次添加一個權限,都會添加到「管理員」角色下,保證「管理員」角色擁有最大權限。

十9、Spring定時任務數據初始化。

這個Demo由於是開放的,因此建立了一個定時任務。每20分鐘執行一次,用Mysql存儲過程從新建立表,從新插入初始化數據。

具體數據看項目中的init/sql下的tables.sql(初始化表),init.data.sql(初始化數據)。

 

 
  1. //定時任務配置文件spring-timer.xml
  2. <task:executor id="executor" pool-size="5" />
  3. <task:scheduler id="scheduler" pool-size="10" />
  4. <task:annotation-driven executor="executor" scheduler="scheduler" />
  5. //Java 代碼 RoleServiceImpl.java
  6. /**
  7. * 每20分鐘執行一次
  8. */
  9. @Override
  10. @Scheduled(cron = "0 0/20 * * * ? ")
  11. public void initData() {
  12. roleMapper.initData();
  13. }

 

二10、集成驗證碼。

shiro

項目中package:com.sojson.common.utils.vcode包是驗證碼的封裝包。

而且提供了一個VerifyCodeUtils.java 的驗證碼工具類。

使用方法參見:CommonController.java類中的getVCode()方法和getGifCode()方法。

驗證碼詳細介紹
Java生成驗證碼合集(一)簡單版
Java生成驗證碼合集(二)GJF版

若是不是Maven項目,下載依賴包。

依賴Jar包下載:

http://pan.baidu.com/s/1c2LUumW 提取密碼:3kv8、或者請加QQ羣:259217951(羣文件內有,有問題能夠交流。)。

備註:點擊文件名下載,附件源來自雲端,只能在本站下載。複製下載連接無效。

Shrio + SSM框架 Demo 源碼下載。

源碼下載

Shiro_SSM_0.1版本下載

備註:點擊文件名下載,附件源來自雲端,只能在本站下載。複製下載連接無效

相關文章
相關標籤/搜索