Shiro Demo 示例(SpringMVC-Mybatis-Shiro-redis)
Shiro Demo 準備工作
運行前申明
- 請看完本頁面的所有細節,對你掌握這個項目來說很重要,別一上來就搞,你不爽,我也不爽。
- 本項目需要一定的Java功底,需要對
SpringMvc
,Mybatis
,有基本的了解,其次對Redis
有了解和使用更佳。 - 本項目理論上,只需要一個
Redis
,然後一個Mysql
和一個有Maven
環境的開發工具即可運行起來。 - 對Reids沒有了解,請看這裏:對Redis的理解,Redis是什麽,Redis和Memcache誰快?。
運行步驟
- 從 Github 下載源碼(不定期更新和修復BUG),導入到
Eclipse
MyEclipes
、Idea
類似開發工具。 - 解決編譯錯誤,修改
JDK
為1.7
以上(請勿使用工具自帶JDK
)。 - 在
Mysql
數據庫中創建一個數據庫,庫名隨便。 - 從項目
/init/sql/
下,先執行tables.sql
創建表,再運行init.data.sql
插入初始化數據。 - 再修改配置
jdbc.properties
把數據庫鏈接改成您的。 - 安裝Redis服務,如果您沒用過,或者沒安裝,請看這裏==>Redis 安裝,以及註意事項都在裏面有說明。Redis啟動報錯請看這裏:Please see the documentation included with the binary distributions for more details on the --maxheap flag.
- 安裝完畢後,修改配置:
spring-cache.xml
,如果是本地,無序修改,啟動Redis
,如對Redis
不了解的同學,建議別設置密碼。 - 運行項目,如果還有錯誤請參考異常信息,並解決,如果實在不能解決,請加QQ群交流,群需要付費
5
元,加群請看右側菜單。 - 項目帳號和線上Demo一致:管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用 sojson
線上Demo說明
- Demo已經部署到線上,地址是:http://shiro.itboy.net
- 管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用 sojson
- 你可以註冊自己的帳號,然後用管理員賦權限給你自己的帳號,但是,每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版本,這樣你遇到的問題會比較少。
升級內容:
- 修復了些許BUG,優化了語法。
- 0.1版本限制較多,比如要部署到Tomcat Root下才能正常運行,就是用
http://localhost:8080
方式訪問。 - 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
。
本教程包含的內容
- SSM(SpringMVC + Spring +
Mybatis
)框架的增刪改查(含分頁),所以如果框架小白也是可以看看的。 View
層主要是Freemarker,但是為了考慮到好多人還使用的是JSP,也有一個頁面是用JSP實現的,並且框架支持Freemarker 和JSP
雙View
展示(優先找Freemarker)。- Shiro + Redis 的集成,也提供Ehcache的依賴Jar。
Shiro
初始權限動態加載。Shiro
自定義權限校驗Filter
定義,及功能實現。Shiro
Ajax請求權限不滿足,攔截後解決方案。Shiro
Freemarker標簽使用。Shiro
JSP標簽使用。Shiro
登錄後跳轉到最後一個訪問的頁面。- 用戶禁止登錄
Demo
。 - 在線顯示,在線用戶管理(踢出登錄)。
- 登錄註冊密碼加密傳輸
Demo
(詳細請見下面講解)。 - 密碼修改。
- 用戶個人中心。
- 權限的增刪改查。
- 角色的增刪改查。
- 權限
->
角色->
用戶之間的關系維護。 - 管理員權限的自動添加(當有一個權限創建,自動添加到管理員角色下,保證管理員是最大權限)。
- Spring定時任務數據化數據。
- 集成多種驗證碼(包括動態的gif驗證碼哦)。
- 一個帳號多處登錄限制,踢出用戶。
- 後續會陸陸續續升級... ...
一、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
中配置
- <property name="filterChainDefinitions" >
- <value>
- /** = anon
- /page/login.jsp = anon
- /page/register/* = anon
- /page/index.jsp = authc
- /page/addItem* = authc,roles[數據管理員]
- /page/file* = authc,roleOR[普通用戶,數據管理員]
- /page/listItems* = authc,roleOR[數據管理員,普通用戶]
- /page/showItem* = authc,roleOR[數據管理員,普通用戶]
- /page/updateItem*=authc,roles[數據管理員]
- </value>
- </property>
本教程采用動態加載,你可以從數據庫裏讀取然後拼接成shiro要的數據。
- <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個攔截器,具體功能看代碼以及代碼註釋。
- <bean id="shiroManager" class="com.sojson.core.shiro.service.impl.ShiroManagerImpl"/>
- <bean id="login" class="com.sojson.core.shiro.filter.LoginFilter"/>
- <bean id="role" class="com.sojson.core.shiro.filter.RoleFilter"/>
- <bean id="permission" class="com.sojson.core.shiro.filter.PermissionFilter"/>
- <bean id="simple" class="com.sojson.core.shiro.filter.SimpleAuthFilter"/>
- <property name="filters">
- <util:map>
- <entry key="login" value-ref="login"></entry>
- <entry key="role" value-ref="role"></entry>
- <entry key="simple" value-ref="simple"></entry>
- <entry key="permission" value-ref="permission"></entry>
- </util:map>
- </property>
六、Shiro Ajax請求權限不滿足,攔截後解決方案。
這裏有一個前提,我們知道Ajax不能做頁面redirect
和forward
跳轉,所以Ajax請求假如沒登錄,那麽這個請求給用戶的感覺就是沒有任何反應,而用戶又不知道用戶已經退出了。解決代碼如下:
- //Java代碼,判斷如果是Ajax請求,然後並且沒登錄,那麽就給予返回JSON,login_status = 300,message = 當前用戶沒有登錄!
- if (ShiroFilterUtils.isAjax(request)) {// ajax請求
- Map<String,String> resultMap = new HashMap<String, String>();
- LoggerUtils.debug(getClass(), "當前用戶沒有登錄,並且是Ajax請求!");
- resultMap.put("login_status", "300");
- resultMap.put("message", "\u5F53\u524D\u7528\u6237\u6CA1\u6709\u767B\u5F55\uFF01");//當前用戶沒有登錄!
- ShiroFilterUtils.out(response, resultMap);
- }
- //前端代碼
- if(result.login_status == 300){
- layer.msg(result.message);//當前用戶沒有登錄!
- }
七、Shiro Freemarker標簽使用。
Freemarker使用Shiro 標簽的介紹:https://www.sojson.com/blog/143.html
八、Shiro JSP標簽使用。
JSP使用Shiro 標簽的介紹:https://www.sojson.com/blog/144.html
九、Shiro 登錄後跳轉到最後一個訪問的頁面。
在 Java 中就可以這樣獲取上一個地址:
- //上一個瀏覽的非Ajax的地址,在登錄後,取得地址,如果不為null,那麽就跳轉過去。
- String url = (String) request.getAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE);
- //shiro也有他的方法。詳細看下面。
如果需要保存登錄之前的Request信息,那麽需要在Login攔截的Filter中先保存:
- @Override
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
- throws Exception {
- //保存Request和Response,登錄後可以取到
- saveRequestAndRedirectToLogin(request, response);
- return Boolean.FALSE ;
- }
- //登錄後,取到之前的Request中的一些信息。
- SavedRequest saveRequest = WebUtils.getSavedRequest(request);
- saveRequest.getMethod();//之前的請求方法
- saveRequest.getQueryString();//之前請求的條件
- saveRequest.getRequestURI();//之前請求的路徑
- saveRequest.getRequestUrl();//之前請求的全路徑
十、用戶禁止登錄Demo
這個功能其實是一個改變用戶數據庫表裏的一個字段,本Demo中:1:有效,0:禁止登錄
然後踢出用戶登錄狀態。代碼詳細請查看CustomSessionManager.java
類的forbidUserById(Long id, Long status)
方法。
而再次登錄的話,需要再登錄,而登錄的地方限制了用戶狀態為(0
:禁止登錄)的用戶登錄。
- /**
- * 查詢要禁用的用戶是否在線。
- * @param id 用戶ID
- * @param status 用戶狀態
- */
- public void forbidUserById(Long id, Long status) {
- //獲取所有在線用戶
- for(UserOnlineBo bo : getAllUser()){
- Long userId = bo.getId();
- //匹配用戶ID
- if(userId.equals(id)){
- //獲取用戶Session
- Session session = shiroSessionRepository.getSession(bo.getSessionId());
- //標記用戶Session
- SessionStatus sessionStatus = (SessionStatus) session.getAttribute(SESSION_STATUS);
- //是否踢出 true:有效,false:踢出。
- sessionStatus.setOnlineStatus(status.intValue() == 1);
- //更新Session
- customShiroSessionDAO.update(session);
- }
- }
- }
十一、在線顯示,在線用戶管理(踢出登錄)
上面的功能依賴這個功能。從Redis中獲取所有有效的Session
- /**
- * 獲取所有的有效Session用戶
- * @return
- */
- public List getAllUser() {
- //獲取所有session
- Collection sessions = customShiroSessionDAO.getActiveSessions();
- List list = new ArrayList();
- for (Session session : sessions) {
- UserOnlineBo bo = getSessionBo(session);
- if(null != bo){
- list.add(bo);
- }
- }
- return list;
- }
踢出後,不能直接退出,要不然用戶感覺莫名其妙。所有增加了一個Filter。SimpleAuthFilter.java
如果標記為踢出,會提示用戶。具體查看源碼以及配合項目的使用。
十二、登錄註冊密碼加密傳輸
這個地方好多人糾結的。比如密碼過於簡單,即使加密後也能破解。如我們把密碼:123456
,加密後就是:e10adc3949ba59abbe56e057f20f883e
這個很容易被識別,導致不安全,現在市面上的MD5破解其實就是把常用的數字,字母進行先加密,然後對比,美其名曰破解MD5。
那怎麽能讓用戶即使使用很簡單的密碼,也發現不了?
本Demo的實現方式是:MD5(登錄帳號 + “固定值” + 密碼),把這個作為密碼,這樣,基本是不可能猜的出來。
- //Java代碼。UserManager.md5Pswd(UUser user);
- /**
- * 加工密碼,和登錄一致。
- * @param user
- * @return
- */
- public static UUser md5Pswd(UUser user){
- //密碼為 email + ‘#‘ + pswd,然後MD5
- user.setPswd(md5Pswd(user.getEmail(),user.getPswd()));
- return user;
- }
- /**
- * 字符串返回值
- * @param email
- * @param pswd
- * @return
- */
- public static String md5Pswd(String email ,String pswd){
- pswd = String.format("%s#%s", email,pswd);
- pswd = MathUtil.getMD5(pswd);
- return pswd;
- }
- //JS代碼
- var pswd = MD5(username +"#" + password);
十三、密碼修改
不講了,和上面原理一致,然後具體看Demo。
十四、用戶個人中心
包含的功能有[個人資料,資料修改,密碼修改,我的權限],具體看Demo。
十五、權限的增刪改查。
本Demo
的設計是遵循RBAC3的思想。https://www.sojson.com/blog/142.html
RBAC個人理解介紹:https://www.sojson.com/blog/141.html
具體實現看Demo。
十六、角色的增刪改查
十七、權限->角色->用戶之間的關系維護
把權限賦給角色。
把角色賦給用戶。
十八、管理員權限的自動添加
這裏每次添加一個權限,都會添加到“管理員”角色下,保證“管理員”角色擁有最大權限。
十九、Spring定時任務數據初始化
這個Demo
因為是開放的,所以創建了一個定時任務。每20分鐘執行一次,用Mysql存儲過程重新創建表,重新插入初始化數據。
具體數據看項目中的init/sql
下的tables.sql(初始化表),init.data.sql(初始化數據)。
- //定時任務配置文件spring-timer.xml
- <task:executor id="executor" pool-size="5" />
- <task:scheduler id="scheduler" pool-size="10" />
- <task:annotation-driven executor="executor" scheduler="scheduler" />
- //Java 代碼 RoleServiceImpl.java
- /**
- * 每20分鐘執行一次
- */
- @Override
- @Scheduled(cron = "0 0/20 * * * ? ")
- public void initData() {
- roleMapper.initData();
- }
二十、集成驗證碼
項目中package:com.sojson.common.utils.vcode
包是驗證碼的封裝包。
並且提供了一個VerifyCodeUtils.java 的驗證碼工具類。
使用方法參見:CommonController.java
類中的getVCode()
方法和getGifCode()
方法。
驗證碼詳細介紹、
Java生成驗證碼合集(一)簡單版 、
Java生成驗證碼合集(二)GJF版 。
二十一、一個帳號多處登錄限制,踢出用戶。
項目中我們會用到單點登錄,還有用到單個賬號怎麽限制同時只能一個人在線?
Shiro教程(十一)Shiro 控制並發登錄人數限制實現,登錄踢出實現:https://www.sojson.com/blog/158.html
如果不是Maven項目,下載依賴包。
依賴Jar包下載:
項目依賴Jar包,或者請加QQ群:259217951(群文件內有,有問題可以交流。)。
備註:點擊文件名下載,附件源來自雲端,只能在本站下載。復制下載鏈接無效。
Shiro + SSM框架 Demo 源碼下載。
源碼下載
Shiro_SSM_0.1版本下載(求你了,別下。)
Shiro_SSM_0.2版本下載(最後更新時間,2017年5月9日 )
備註:點擊文件名下載,附件源來自雲端,只能在本站下載。復制下載鏈接無效。
如果本文對你有幫助,那麽請你贊助我,讓我更有激情的寫下去,幫助更多的人。
版權所屬:SO JSON在線解析
原文地址:https://www.sojson.com/shiro
轉載時必須以鏈接形式註明原始出處及本聲明。
Shiro Demo 示例(SpringMVC-Mybatis-Shiro-redis)