Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权
一、Shiro授權:
1、授權與權限:
(1)授權:訪問控制,必須具有該資源的訪問權限才可以訪問該資源。
(2)權限模型:標準權限數據模型包括 :用戶、角色、權限(包括資源和權限)、用戶角色關系、角色權限關系。
(3)權限分配:通過UI界面方便給用戶分配權限,對上邊權限模型進行增、刪、改、查操作。
(4)權限控制:
第一種:基于角色的權限控制:根據角色判斷是否有操作權限,因為角色的變化性較高,如果角色修改需要修改控制代碼,系統可擴展性不強。
第二種:基于資源的權限控制:根據資源權限判斷是否有操作權限,因為資源較為固定,如果角色修改或角色中權限修改不需要修改控制代碼,使用此方法系統可維護性很強。建議使用。
(5)權限管理的解決方案:
①對于粗顆粒權限管理,建議在系統架構層面去解決,寫系統架構級別統一代碼(基礎代碼)。
粗顆粒權限:比如對系統的url、菜單、jsp頁面、頁面上按鈕、類方法進行權限管理,即對資源類型進行權限管理。
②對于細顆粒權限管理:細顆粒權限管理是系統的業務邏輯,業務邏輯代碼不方便抽取統一代碼,建議在系統業務層進行處理。
粗顆粒權限:比如用戶id為001的用戶信息(資源實例)、類型為t01的商品信息(資源實例),對資源實例進行權限管理,可以理解為對數據級別的權限管理。
?
2、授權流程:
(1)對subject進行授權,調用方法isPermitted("permission串");
(2)SecurityManager執行授權,通過ModularRealmAuthorizer執行授權;
(3)ModularRealmAuthorizer執行realm(自定義的CustomRealm)從數據庫查詢權限數據,調用realm的授權方法:doGetAuthorizationInfo;
(4)realm從數據庫查詢權限數據,返回ModularRealmAuthorizer;
(5)ModularRealmAuthorizer調用PermissionResolver進行權限串比對;
(6)如果比對后,isPermitted中"permission串"在realm查詢到權限數據中,說明用戶訪問permission串有權限,否則 沒有權限,拋出異常。
?
3、Shiro 支持三種方式的授權:
(1)編程式:通過寫if/else 授權代碼塊完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有權限
} else {
//無權限
}
(2)注解式:通過在執行的Java方法上放置相應的注解完成:
@RequiresRoles("admin")
public void hello() {
//有權限
}
(3)JSP/GSP 標簽:在JSP/GSP 頁面通過相應的標簽完成:
<shiro:hasRole name="admin">
<!— 有權限—>
</shiro:hasRole>
?
?
二、Shiro授權示例程序:
1、入門的Shiro授權程序:
(1)編寫shiro-permission.ini文件:
shiro-permission.ini文件里邊的內容相當于在數據庫查詢出來的;
#用戶 [users] #用戶zhangsan的密碼是123,此用戶具有role1和role2兩個角色 zhangsan=123456,role1,role2 wangwu=123456,role2#權限 [roles] #角色role1對資源user擁有create、update權限 role1=user:create,user:update role2=user:create,items:delete role3=user:create權限標識符號規則:資源:操作:實例(中間使用半角:分隔)
user:create:01? 表示對用戶資源的01實例進行create操作。
user:create? ? 表示對用戶資源進行create操作,相當于user:create:*,對所有用戶資源實例進行create操作。
user:*:01? 表示對用戶資源實例01進行所有操作。
(2)程序編寫:
//shiro的授權測試: public class AuthorizationTest {//角色授權、資源授權測試:@Testpublic void testAuthorization(){Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");SecurityManager securityManager = factory.getInstance();SecurityUtils.setSecurityManager(securityManager);SecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");try {subject.login(token);} catch (AuthenticationException e) {e.printStackTrace();}System.out.println("認證狀態:" + subject.isAuthenticated());//認證通過之后執行授權://基于角色的授權//hasRole傳入角色標識:boolean ishasRole = subject.hasRole("role1");System.out.println("單個角色判斷" + ishasRole);//hasAllRoles是否擁有多個角色:boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));System.out.println("多個角色判斷" + hasAllRoles);// 使用check方法進行授權,如果授權不通過會拋出異常subject.checkRole("role2");//基于資源的授權://isPermitted傳入權限標識符boolean isPermitted = subject.isPermitted("user:create:1");System.out.println("單個權限判斷" + isPermitted);boolean isPermittedAll = subject.isPermittedAll("user:create:1","user:delete");System.out.println("多個權限判斷" + isPermittedAll);// 使用check方法進行授權,如果授權不通過會拋出異常subject.checkPermission("items:delete:1");} }(3)執行結果:
至此,Shiro授權入門程序就完成了。在這個程序中,我們讀取的是在shiro.ini配置文件中靜態配置好的權限內容,但是在實際開發,我們通常是從數據庫中查詢用戶所擁有的權限信息,因此,我們需要使用自定義的Realm進行從數據庫中查詢用戶的權限信息。
?
2、自定義realm進行授權:
上面的程序是通過shiro-permission.ini對權限文件進行靜態配置,在實際開發中,都是從數據庫中獲取權限數據。就需要自定義realm,由realm從數據庫查詢權限數據。
realm根據用戶身份查詢權限數據,將權限數據返回給authorizer(授權器)。
(1)自定義realm:
//自定義的Realm,需要繼承AuthorizingRealm,并且重寫這個類的兩個方法 public class CustomRealm extends AuthorizingRealm{// 設置realm的名稱@Overridepublic void setName(String name) {super.setName("customRealm");}// 用于授權@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//從principals獲取身份信息//將getPrimaryPrincipal方法返回值轉為真實身份(在上邊的doGetAuthenticationInfo認證通過填充到SimpleAuthenticationInfo中的身份類型)String userCode = (String) principals.getPrimaryPrincipal();//根據身份信息獲取權限信息//連接數據庫//模擬從數據庫獲取到數據List<String> permissions = new ArrayList<String>();permissions.add("user:create");//用戶的創建permissions.add("items:add");//商品添加權限//查到權限數據,返回授權信息(要包括上邊的permissions)SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();//將上邊查詢到授權信息填充到simpleAuthorizationInfo對象中simpleAuthorizationInfo.addStringPermissions(permissions);return simpleAuthorizationInfo;} }(2)編寫shiro-realm.ini文件:
在shiro-realm.ini文件中配置自定義的realm,將realm設置到securityManager中。
[main] #自定義的realm customRealm=com.zwp.shiro.realm.CustomRealm #將realm設置到securityManager,相當于spring中的注入 securityManager.realms=$customRealm(3)測試:
// 自定義realm進行資源授權測試@Testpublic void testAuthorizationCustomRealm() {Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");SecurityManager securityManager = factory.getInstance();SecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();// 創建token令牌UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");// 執行認證try {subject.login(token);} catch (AuthenticationException e) {e.printStackTrace();}System.out.println("認證狀態:" + subject.isAuthenticated());// 認證通過后執行授權// 基于資源的授權,調用isPermitted方法會調用CustomRealm從數據庫查詢正確權限數據// isPermitted傳入權限標識符,判斷user:create:1是否在CustomRealm查詢到權限數據之內boolean isPermitted = subject.isPermitted("user:create:1");System.out.println("單個權限判斷" + isPermitted);boolean isPermittedAll = subject.isPermittedAll("user:create:1","user:create");System.out.println("多個權限判斷" + isPermittedAll);// 使用check方法進行授權,如果授權不通過會拋出異常subject.checkPermission("items:add:1");}(4)測試結果:
至此,Shiro使用自定義Realm進行授權的程序就完成了。
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Shiro框架:Shiro简介、登陆认证
- 下一篇: SSM整合Shiro进行登陆认证和授权详