Shiro安全框架之權限認證(授權)
第一講、權限認證核心要素
權限認證,也就是訪問控制,即在應用中控制誰能訪問哪些資源。 在權限認證中,最核心的三個要素是:權限,角色和用戶;
Authorization has three core elements that we reference quite a bit in Shiro: permissions, roles, and users.
權限permissions,即操作資源的權利,比如訪問某個頁面,以及對某個模塊的數據的添加,修改,刪除,查看的權利; 角色,是權限的集合,一中角色可以包含多種權限; 用戶,在 Shiro 中,代表訪問系統的用戶,即 Subject;
第二講、授權
一、編程式授權Programmatic Authorization
在pom添加junit依賴
<!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
新建common包 ShiroUtil.java用於封裝shiro/HelloWorld.java
將ini文件設置成參數configFile動態添加進來解析將用戶名和密碼也動態添加進來
package com.guo.common; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; public class ShiroUtil { public static Subject login(String configFile,String userName,String password){ // 讀取配置文件,初始化SecurityManager工廠 Factory<SecurityManager> factory=new IniSecurityManagerFactory(configFile); // 獲取securityManager實例 SecurityManager securityManager=factory.getInstance(); // 把securityManager實例綁定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到當前執行的用戶 Subject currentUser=SecurityUtils.getSubject(); // 創建token令牌,用戶名/密碼 UsernamePasswordToken token=new UsernamePasswordToken(userName, password); try{ // 身份認證 currentUser.login(token); System.out.println("身份認證成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份認證失敗!"); } return currentUser; } }
1、基於角色的訪問控制 Role-Based Authorization
(a)在resource/新建個shiro_role.in
[users] Robin=123456,role1,role2 Tom=123,role1
用名戶Robin 密碼123456 角色是role1 role2 表示權限
(b)方法
hasRole(String roleName)
判斷是否有這個角色,返回值是布爾類型,只判斷一個
hasRoles(List<String> roleNames)
可以判斷多個角色是否擁有,返回布爾型數組
hasAllRoles(Collection<String> roleNames) 判斷角色是否全部擁有,要全都有才返回true
在shiro包下新建個單元測試junittestcase,RoleTest用於測試上述方法
@Test public void testHasRole() { Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "Robin", "123456"); System.out.println(currentUser.hasRole("role1")?"有role1這個角色":"沒有role1這個角色"); boolean []results=currentUser.hasRoles(Arrays.asList("role1","role2","role3")); System.out.println(results[0]?"有role1角色":"沒有role1角色"); System.out.println(results[1]?"有role2角色":"沒有role2角色"); System.out.println(results[2]?"有role3角色":"沒有role3角色"); System.out.println(currentUser.hasAllRoles(Arrays.asList("role1","role2"))?"有role1 role2角色":"沒有role1 role2角色"); currentUser.logout(); // 退出當前用戶 }
除上述三個方法外還有
checkRole(String roleName)
檢查是否擁有角色,沒有的話拋出異常而不是返回布爾值false
checkRoles(Collection<String> roleNames)
checkRoles(String... roleNames)
2 基於權限的訪問控制
(a)再新建個shiro_permission.ini
[users] Robin=123456,role1,role2 Tom=123,role1 [roles] role1=user:select role2=user:add,user:update
因為基於權限所以 添加角色權限,role1有查找權限,role2有添加 修改權限
(b)方法
isPermitted(Permission p)
判斷角色是否有權限,返回布爾類型
isPermitted(List<Permission> perms)
isPermittedAll(Collection<Permission> perms)
因為Permission是接口,不能實例化,實例化需實例化它的實現類,太麻煩所以實際項目中不用,直接用下面這種形式,直接傳字符串
isPermitted(String perm)
isPermitted(String... perms)
isPermittedAll(String... perms)
(c)再新建個單元測試PermissionTest
@Test public void testIsPermitted() { Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "Robin", "123456"); // Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "jack", "123"); System.out.println(currentUser.isPermitted("user:select")?"有user:select這個權限":"沒有user:select這個權限"); System.out.println(currentUser.isPermitted("user:update")?"有user:update這個權限":"沒有user:update這個權限"); boolean results[]=currentUser.isPermitted("user:select","user:update","user:delete"); System.out.println(results[0]?"有user:select這個權限":"沒有user:select這個權限"); System.out.println(results[1]?"有user:update這個權限":"沒有user:update這個權限"); System.out.println(results[2]?"有user:delete這個權限":"沒有user:delete這個權限"); System.out.println(currentUser.isPermittedAll("user:select","user:update")?"有user:select,update這兩個權限":"user:select,update這兩個權限不全有"); currentUser.logout(); // 退出當前用戶 }
除上述三個方法外還有
checkPermission(Permission p)
判斷角色是否有權限,沒有拋出異常
checkPermission(String perm)
checkPermissions(Collection<Permission> perms)
checkPermissions(String... perms)
二,註解式授權
@RequiresAuthentication 要求當前 Subject 已經在當前的 session 中被驗證通過才能被訪問或調用。
@RequiresGuest 要求當前的 Subject 是一個"guest",也就是說,他們必須是在之前的 session 中沒有被驗證或被記住才
能被訪問或調用。
@RequiresPermissions("account:create") 要求當前的 Subject 被允許一個或多個權限,以便執行註解的方法。
@RequiresRoles("administrator") 要求當前的 Subject 擁有所有指定的角色。如果他們沒有,則該方法將不會被執行,而
且 AuthorizationException 異常將會被拋出。
@RequiresUser RequiresUser 註解需要當前的 Subject 是一個應用程序用戶才能被註解的類/實例/方法訪問或調用。一個“應
用程序用戶”被定義為一個擁有已知身份,或在當前 session 中由於通過驗證被確認,或者在之前 session 中的‘RememberMe‘
服務被記住
三,Jsp 標簽授權
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
Guest 標簽:用戶沒有身份驗證時顯示相應信息,即遊客訪問信息;
User 標簽:用戶已經身份驗證/記住我登錄後顯示相應的信息;
Authenticated 標簽:用戶已經身份驗證通過,即 Subject.login 登錄成功,不是記住我登錄的。
notAuthenticated 標簽:用戶沒有身份驗證通過,即沒有調用 Subject.login 進行登錄,包括記住我自動登錄
的也屬於未進行身份驗證。
principal 標簽 顯示用戶身份信息,默認調用 Subject.getPrincipal()獲取,即 Primary Principal。
hasRole 標簽 如果當前 Subject 有角色將顯示 body 體內容。
lacksRole 標簽 如果當前 Subject 沒有角色將顯示 body 體內容。
hasAnyRoles 標簽 如果當前 Subject 有任意一個角色(或的關系)將顯示 body 體內容。
hasPermission 標簽 如果當前 Subject 有權限將顯示 body 體內容。
lacksPermission 標簽 如果當前 Subject 沒有權限將顯示 body 體內容。
第三講、Permissions 對權限深入理解
單個權限 query
單個資源多個權限 user:query user:add 多值 user:query,add
單個資源所有權限 user:query,add,update,delete user:*
所有資源某個權限 *:view
實例級別的權限控制
單個實例的單個權限 printer:query:lp7200 printer:print:epsoncolor
所有實例的單個權限 printer:print:*
所有實例的所有權限 printer:*:*
單個實例的所有權限 printer:*:lp7200
單個實例的多個權限 printer:query,print:lp7200
第四講、授權流程
Shiro安全框架之權限認證(授權)