shiro授權入門

1、授權流程

在這裏插入圖片描述

2、三種授權方法

shiro支持三種方式的授權:
1、編程時,通過寫if/else授權代碼

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有權限
} else {
//無權限
}

2、註解式:通過在執行的java方法上放置相應的註解完成:

@RequiresRoles("admin")
public void hello() {
//有權限
}

3、jsp/gsp標籤:

<shiro:hasRole name="admin">
<!— 有權限—>
</shiro:hasRole>

3、按照ini文件的配置形式進行測試

3.1 config/shiro-1.ini裏邊的內容相當於在數據庫。

#用戶
[users]
#用戶zhang的密碼是123,此用戶具有role1和role2兩個角色
zhang=123,role1,role2
wang=123,role2

#權限
[roles]
#角色role1對資源user擁有create、update權限
role1=user:create,user:update
#角色role2對資源user擁有create、delete權限
role2=user:create,user:delete
#角色role3對資源user擁有create權限
role3=user:create

權限標識符規則:資源:操作:實例(中間試驗半角:分割)
user:create:01 表示對用戶資源的01實例進行create操作
user:create:表示對用戶資源進行create操作,相當於user:create:*,對所有用戶資源實例進行create操作

user:*:01 表示對用戶資源實例01進行所有操作
3.2 程序編寫

//構建SecurityManager工廠,IniSecurityManagerFactory可以從ini文件中初始化SecurityManager環境
        Factory<SecurityManager> factory=new IniSecurityManagerFactory("config/shiro-1.ini");

        //創建SecurityManager
        SecurityManager securityManager=factory.getInstance();

        //將SecurityManager設置當前的運行環境中
        SecurityUtils.setSecurityManager(securityManager);

        //從SecurityUtils裏面創建一個subject
        Subject subject=SecurityUtils.getSubject();

        //在認證提交前準備token(令牌),這裏的賬號和密碼,將來是用戶輸入進去
        UsernamePasswordToken token=new UsernamePasswordToken("zhangsan1","123");
        //執行認證提交
        subject.login(token);

        boolean isAuthenticated=subject.isAuthenticated();

        System.out.println("是都認證通過:"+isAuthenticated);
//基於角色的授權
        //hasRole傳入角色標識
        boolean ishasRole=subject.hasRole("role1");
        System.out.println("單個角色判斷"+ishasRole);
        //hasAllRoles是否擁有多個角色
        boolean hasAllRoles=subject.hasAllRoles(Arrays.asList("role1","role2"));
        System.out.println("多個角色判斷"+hasAllRoles);
        //使用check方法進行授權,如果授權不通過拋出異常
        subject.checkRole("role12");


        //基於資源的授權
        boolean isPermitted=subject.isPermitted("user:create:1");
        System.out.println("單個權限判斷"+isPermitted);

        boolean isPermittedAll=subject.isPermittedAll("user:create:1","user:add:1");
        System.out.println("多個權限判斷"+isPermitted);

        //使用check方法進行授權,如果授權不通過則會拋出異常
        subject.checkPermission("user:create:1");

4、自定義realm授權驗證

4.1 上面的程序通過config/shiro-1.ini對權限信息進行靜態配置,實際開發中從數據庫中獲取權限數據,自定義realm,由realm從數據庫查詢權限數據
realm根據用戶身份查詢權限數據,將權限數據返回給authorizer(授權器)。

4.2 自定義realm
在原來自定義的realm中,修改doGetAuthorizationInfo方法

 /**
     * 授權
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //從principalCollection獲取主身份信息
        //將getPrimaryPrincipal方法返回值轉爲真實身份類型(從doGetAuthenticationInfo認證通過 填充到SimpleAuthenticationInfo)
        String userCode=(String)principalCollection.getPrimaryPrincipal();

        /**
         * 根據身份信息獲取權限信息
         * 連接數據庫
         * 模擬從數據庫獲取到數據
         */
        List<String> permissions=new ArrayList<>();
        permissions.add("user:create");
        permissions.add("user:add");

        //查到權限數據,返回授權信息(包括上邊的permissions)
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        //將上邊查詢到授權信息填充到simpleAuthorizationInfo對象中
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

4.3 relam.ini文件

[main]
#自定義 realm
customRealm=com.zhou.dado.shiro1.Test2_Realm
#將realm設置到securityManager
securityManager.realms=$customRealm

4.4測試程序

@Test
	public void testAuthorizationCustomRealm() {

		// 創建SecurityManager工廠
		Factory<SecurityManager> factory = new IniSecurityManagerFactory(
				"classpath:shiro-realm.ini");

		// 創建SecurityManager
		SecurityManager securityManager = factory.getInstance();

		// 將SecurityManager設置到系統運行環境,和spring後將SecurityManager配置spring容器中,一般單例管理
		SecurityUtils.setSecurityManager(securityManager);

		// 創建subject
		Subject subject = SecurityUtils.getSubject();

		// 創建token令牌
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
				"111111");

		// 執行認證
		try {
			subject.login(token);
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			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.5授權流程
1、對subject進行授權,調用方法isPermitted(“permission串”)
2、SecurityManager執行授權,通過ModularRealmAuthorizer進行授權
3、ModularRealmAuthorizer執行realm(自定義的CustomRealm)從數據庫查詢權限數據
調用realm的授權方法:doGetAuthorizationInfo

4、realm從數據庫查詢權限數據,返回ModularRealmAuthorizer
5、ModularRealmAuthorizer調用PermissionResolver進行權限串比對
6、如果比對後,isPermitted中"permission串"在realm查詢到權限數據中,說明用戶訪問permission串有權限,否則 沒有權限,拋出異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章