shiro权限管理基本原理和实现的整理
shiro權限管理基本原理和實現(xiàn)的整理
引言:這兩天學習了一個對權限管理的新的框架shiro,在這里做一個總結,既為了幫助有需要的人,也方便自己以后來回顧。
本篇文章主要針對下面幾個關鍵點來說明:
1. shiro簡介
2. 集成spring,快速搭建環(huán)境
3. shiro認證(即登錄,重點)
4. shiro授權(重點)
5. shiro會話管理(Session)
6. shiro緩存(remember Me)
下面就讓我來根據(jù)這六點,詳細的說明一下shiro的基礎原理和操作實現(xiàn)。
一、shiro簡介
(1)什么是shiro?
Apache Shiro 是 Java 的一個安全(權限)框架。
? Shiro 可以非常容易的開發(fā)出足夠好的應用,其不僅可以用在
JavaSE 環(huán)境,也可以用在 JavaEE 環(huán)境。
? Shiro 可以完成:認證、授權、加密、會話管理、與Web 集成、 緩存
等。
? 下載:下載地址
shiro的架構:
二.shiro集成spring所做的準備工作,本次的案例是集成SpringMvc,一些基本的配置已經(jīng)忽略。
1.導入jar包
2.在web.xml里面加入shiro的過濾器
3.創(chuàng)建二個shiro的配置文件applicationContext.xml和ehcache.xml
在applicationContext.xml配置文件中,我們需要加入這么幾樣東西:
1) 配置 SecurityManager!
2)配置 CacheManager.
<--需要加入 ehcache 的 jar 包及配置文件. --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"><!-- Set a net.sf.ehcache.CacheManager instance here if you already have one. If not, a new onewill be creaed with a default config:<property name="cacheManager" ref="ehCacheManager"/> --><!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you wanta specific Ehcache configuration to be used, specify that here. If you don't, a defaultwill be used.: --><property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean>3)配置 Realm
<!-- 3. 配置 Realm 3.1 直接配置實現(xiàn)了 org.apache.shiro.realm.Realm 接口的 bean--> <bean id="jdbcRealm" class="com.atguigu.shiro.realms.ShiroRealm"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="MD5"></property><property name="hashIterations" value="1024"></property></bean></property></bean><bean id="secondRealm" class="com.atguigu.shiro.realms.SecondRealm"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="SHA1"></property><property name="hashIterations" value="1024"></property></bean></property></bean>4)配置 LifecycleBeanPostProcessor
4. 配置 LifecycleBeanPostProcessor. 可以自定的來調(diào)用配置在 Spring IOC 容器中 shiro bean 的生命周期方法. --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!-- Enable Shiro Annotations for Spring-configured beans. Only run afterthe lifecycleBeanProcessor has run: -->5)啟用 IOC 容器中使用 shiro 的注解.
<!-- 5. 啟用 IOC 容器中使用 shiro 的注解. 但必須在配置了 LifecycleBeanPostProcessor 之后才可以使用. --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor"/><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean>6)配置 ShiroFilter.
6.1 id 必須和 web.xml 文件中配置的 DelegatingFilterProxy 的 <filter-name> 一致.若不一致, 則會拋出: NoSuchBeanDefinitionException. 因為 Shiro 會來 IOC 容器中查找和 <filter-name> 名字對應的 filter bean.--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login.jsp"/><property name="successUrl" value="/list.jsp"/><property name="unauthorizedUrl" value="/unauthorized.jsp"/><!-- <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property> --><!-- 配置哪些頁面需要受保護. 以及訪問這些頁面需要的權限. 1). anon 可以被匿名訪問2). authc 必須認證(即登錄)后才可能訪問的頁面. 3). logout 登出.4). roles 角色過濾器--><property name = "filterChainDefinitions"><value>/login.jsp = anon/shiro/login = anon/shiro/logout = logout/user.jsp = roles[user]/admin.jsp = roles[admin]#everything else requires authentication/** = authc</value></property></bean>---------》配置完了applicationContext.xml 我們接下來配置ehcache.xml
ehcache.xml里面配置的都是接下來我們要說的關于緩存的一些信息,暫且可以忽略。
4.代碼實現(xiàn)。
這里我將用幾個簡單的邏輯類和jsp頁面來完成對登錄授權訪問的驗證,為了方便,我先把全部代碼粘上,后面一一解釋。
1)創(chuàng)建兩個Realm實現(xiàn)類 繼承AuthorizingRealm
2)創(chuàng)建ShiroHandler,來處理我們要進行的邏輯
@Controller @RequestMapping("/shiro/") public class ShiroHandler {@Autowiredprivate ShiroService shiroService;@RequestMapping("/testShiroannotation")public String testShiroannotation(HttpSession session) {shiroService.testMethod();session.setAttribute("key","value13245");return "redirect:/list.jsp";}@RequestMapping("login")public String login(@RequestParam("username")String username,@RequestParam("password")String password) {System.out.println(password);Subject currentUser = SecurityUtils.getSubject();if(!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken(username,password);token.setRememberMe(true);try {//執(zhí)行登錄currentUser.login(token);} catch (Exception e) {System.out.println("登錄失敗:"+e.getMessage());}}return "redirect:/list.jsp";} }3)創(chuàng)建業(yè)務邏輯層service
public class ShiroService {@RequiresRoles(value={"admin"})public void testMethod() {System.out.println("test service time:"+new Date());Session session =SecurityUtils.getSubject().getSession();Object val = session.getAttribute("key");System.out.println("Service SessionVal:"+val);} }4)創(chuàng)建幾個簡單的網(wǎng)頁,來實現(xiàn)登錄、跳轉(zhuǎn)、分配權限
admin.jsp模擬管理員才能訪問的頁面
user.jsp模擬普通用戶訪問的頁面
<body> User Page </body>login.jsp模擬登錄頁面
<body> Login Page<form action="shiro/login" method="post">username:<input type="text" name="username"><br><br>password: <input type="password" name = "password"><br><br><input type="submit" value="Submit"> </form> </body>unauthorized.jsp用于跳轉(zhuǎn)到?jīng)]有授權的頁面
<body> Unauthorized Page </body>list.jsp用來模擬登錄成功跳轉(zhuǎn)頁面
<body> <h4>List Page</h4> </br>WelCome:<shiro:principal></shiro:principal><shiro:hasRole name="admin"></br><a href="admin.jsp">Admin Page</a></br></shiro:hasRole><shiro:hasRole name="user"></br><a href="user.jsp">User Page</a></br></shiro:hasRole></br><a href="shiro/testShiroannotation">TestShiroannotation</a></br><a href="shiro/logout">Logout</a> </body>三、認證(因為上面代碼都粘上了,所以我這里講解的時候就截取關鍵部分)
shiro的認證,說白了就是登錄,我們在handler類里面有l(wèi)ogin方法
圖解:
角色:
? 身份驗證:一般需要提供如身份 ID 等一些標識信息來表明登錄者的身
份,如提供 email,用戶名/密碼來證明。
? 在 shiro 中,用戶需要提供 principals (身份)和 credentials(證
明)給 shiro,從而應用能驗證用戶身份:
? principals:身份,即主體的標識屬性,可以是任何屬性,如用戶名、
郵箱等,唯一即可。一個主體可以有多個 principals,但只有一個
Primary principals,一般是用戶名/郵箱/手機號。
? credentials:證明/憑證,即只有主體知道的安全值,如密碼/數(shù)字證
書等。
? 最常見的 principals 和 credentials 組合就是用戶名/密碼了
流程:
1.通過login.jsp頁面收集到用戶輸入的username和password
2.首先handler調(diào)用 Subject.login(token) 進行登錄,其會自動委托給SecurityManager
3. SecurityManager 負責真正的身份驗證邏輯;它會委托給Authenticator 進行身份驗證;
4.Authenticator 才是真正的身份驗證者,Shiro API 中核心的身份認證入口點,此處可以自定義插入自己的實現(xiàn);
5.Authenticator 可能會委托給相應的 AuthenticationStrategy 進行多 Realm 身份驗證,默認 ModularRealmAuthenticator 會調(diào)用AuthenticationStrategy 進行多 Realm 身份驗證;
6. Authenticator 會把相應的 token 傳入 Realm,從 Realm 獲取身份驗證信息,如果沒有返回/拋出異常表示身份驗證失敗了。此處
可以配置多個Realm,將按照相應的順序及策略進行訪問。
7.創(chuàng)建Realm類接收handler傳來的token,完成對用戶名和密碼的校驗(Realm類上面代碼已經(jīng)創(chuàng)建)
四、授權
Shiro 支持三種方式的授權:
1– 編程式:通過寫if/else 授權代碼塊完成
2– 注解式:通過在執(zhí)行的Java方法上放置相應的注解完成,沒有權限將拋出相應的異常
3– JSP/GSP 標簽:在JSP/GSP 頁面通過相應的標簽完成
授權的底層原理實現(xiàn):
? 1、首先調(diào)用 Subject.isPermitted*/hasRole* 接口,其會委托給SecurityManager,而 SecurityManager 接著會委托給 Authorizer;
? 2、 Authorizer是真正的授權者,如果調(diào)用如 isPermitted(“user:view”),其首先會通過? PermissionResolver 把字符串轉(zhuǎn)換成相應的 Permission 實例;
? 3、在進行授權之前,其會調(diào)用相應的 Realm 獲取 Subject 相應的角色/權限用于匹配傳入的角色/權限;
? 4、 Authorizer 會判斷 Realm 的角色/權限是否和傳入的匹配,如果有多個Realm,會委托給 ModularRealmAuthorizer 進行循環(huán)判斷,
如果匹配如 isPermitted*/hasRole* 會返回true,否則返回false表示 授權失敗。
兩張驗證有關的表格:
(1)編程式的實驗在上面realm類中代碼已經(jīng)體現(xiàn),下面我截取出主要部分。
Object credentials =null;if("admin".equals(username)) {credentials ="038bdaf98f2037b31f1e75b5b4c9b26e";}else if("user".equals(username)) {credentials ="098d2c478e9c11555ce2823231e02ec1";}(2)注解的方式實現(xiàn),可以在service的相關方法上面寫注解,也可以直接在handler或者controller類上面寫注解。注意:當service類上面有@trationcal事務注解時,不能在service上寫注解,只能在controller類上寫注解。
注解的話有下面幾種,我們選擇其中一個來舉例:
我們可以為一個service中的某個方法寫權限注解,來限制某個用戶是否能訪問某個方法,從而實現(xiàn)限制訪問某個頁面的目的。
同樣,注解的方式也能在controller層使用
3)通過shiro標簽在jsp頁面進行授權
這里通過list.jsp頁面來進行頁面訪問的授權
我們可以看到,當角色的身份誰是admin時,可以訪問admin的頁面,是user時,可以訪問user的頁面,但是由于我們前面代碼給的權限,admin可以同時訪問這兩個頁面,但是user就只能訪問user的頁面而不能訪問admin的頁面,剩下的沒有給授權限制的頁面,兩種角色都能訪問。
五、會話管理
概述:Shiro 提供了完整的企業(yè)級會話管理功能,不依賴于底層容器(如web容器tomcat),不管 JavaSE 還是 JavaEE 環(huán)境都可以 使用,提供了會話管理、會話事件監(jiān)聽、會話存儲/持久化、容器無關的集群、失效/過期支持、對Web 的透明支持、 SSO 單點登錄的支持 等特性。
shiro對實現(xiàn)session的增刪改查操作的主要接口是sessionDao。
如果我們需要對session實現(xiàn)增刪改查操作的話,那么我們需要增加如下配置,并且創(chuàng)建SessionDao的類
如果不需要實現(xiàn)對session的操作,那么我們來簡單示范一下:
(1)我們在controller中對用HttpSession對session添加key value。
六、shiro緩存
(1)緩存的話分兩種緩存:
1.Realm 緩存
? Shiro 提供了 CachingRealm,其實現(xiàn)了CacheManagerAware 接口,提供了緩存的一些基礎實現(xiàn);
? AuthenticatingRealm 及 AuthorizingRealm 也分別提供了對AuthenticationInfo 和 AuthorizationInfo 信息的緩
存。
2.Session 緩存
? 如 SecurityManager 實現(xiàn)了 SessionSecurityManager,其會判斷 SessionManager 是否實現(xiàn)了CacheManagerAware 接口,如果實現(xiàn)了會把CacheManager 設置給它。
? SessionManager 也會判斷相應的 SessionDAO(如繼承自CachingSessionDAO)是否實現(xiàn)了CacheManagerAware,如果實現(xiàn)了會把 CacheManager設置給它
? 設置了緩存的 SessionManager,查詢時會先查緩存,如果找不到才查數(shù)據(jù)庫。
我們常用的緩存就是rememberMe
(2)rememberMe
概述:
? Shiro 提供了記住我(RememberMe)的功能,比如訪問如淘寶等一些網(wǎng)站時,關閉了瀏覽器,下次再打開時還是能記住你是誰,下次訪問時無需再登錄即可訪問,基本流程如下:
? 1、首先在登錄頁面選中 RememberMe 然后登錄成功;如果是瀏覽器登錄,一般會把 RememberMe 的Cookie 寫到客戶端并
保存下來;
? 2、關閉瀏覽器再重新打開;會發(fā)現(xiàn)瀏覽器還是記住你的;
? 3、訪問一般的網(wǎng)頁服務器端還是知道你是誰,且能正常訪問;
? 4、但是比如我們訪問淘寶時,如果要查看我的訂單或進行支付時,此時還是需要再進行身份認證的,以確保當前用戶還是你。
這個比較簡單,我們只需要在controller中添加如下代碼:
我們還可以在配置文件中設置時長:
在applicationContext.xml中的securityManager bean中添加如下代碼,value就是代表生效的時長,以秒為單位。
以上就是我對shiro基礎的一些介紹,因為還沒有時間深入研究,講的都比較淺顯,等后面掌握之后還會更新內(nèi)容。
總結
以上是生活随笔為你收集整理的shiro权限管理基本原理和实现的整理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QtCreator插件开发(四)——Qt
- 下一篇: Linux系统中xz命令用法详解(压缩和