1. 程式人生 > >Shiro學習之許可權認證

Shiro學習之許可權認證

許可權認證也就是訪問控制,即在應用中控制誰能訪問哪些資源.
在許可權認證中,最核心的是三個要素是:許可權,角色和使用者.
許可權,即操作資源的權力,比如訪問某個頁面,以及對某個模組的資料的新增,修改,刪除,檢視的權利(CRUD).
角色,是許可權的集合,一個角色可以包含多種許可權
使用者,在shiro中代表訪問系統的使用者,即subject

授權

  • 程式設計式授權,基於角色和許可權的訪問控制
  • 註解授權,jsp標籤授權

1.基於角色的訪問控制
配置shiro_role.ini檔案

[users]
yyt=123,role1,role2
jack=1234,role1

規則即:“使用者名稱=密碼,角色1,角色2”,如果需要在應用中判斷使用者是否有相應角色,就需要在相應的Realm中返回角色資訊,也就是說Shiro不負責維護使用者-角色資訊,需要應用提供,Shiro只是提供相應的介面方便驗證,後續會介紹如何動態的獲取使用者角色。

首先我將重複的程式碼封裝成一個方法,傳入配置檔案的名字,使用者名稱,密碼

package com.kingsky;

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 configPath, String userName, String passWord) { // 讀取配置檔案,初始化SecurityManager工廠 Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:"
+configPath); // 獲取到SecurityManager例項 SecurityManager securityManager = factory.getInstance(); // 把SecurityManager繫結到SecurityUtils中 SecurityUtils.setSecurityManager(securityManager); // 得到當前使用者 Subject subject = SecurityUtils.getSubject(); // 建立Token令牌,使用者名稱/密碼 UsernamePasswordToken passwordToken = new UsernamePasswordToken(userName, passWord); // 驗證登入 會丟擲異常 try { subject.login(passwordToken); System.out.println("身份驗證成功!!!"); } catch (AuthenticationException e) { e.printStackTrace(); System.out.println("身份驗證失敗!!!!"); } return subject; } }

在測試類中進行測試,我沒有使用junit進行測試,我是直接使用main方法測試
1.1測試subject.hasRole(String roleName) 返回值是boolean

public class TestRole {
    public static void main(String[] args) {
        Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
        //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
        System.out.println(subject.hasRole("role2")?"有role2這個角色":"沒有role2這個角色");
    }
}

控制檯的輸出是:有role2這個角色,
如果是換成了jack,控制檯輸出的是:沒有role2這個角色

1.2測試subject.hasRoles(List roles) 返回值是boolean[]

Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
//Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
boolean[] results=subject.hasRoles(Arrays.asList("role1","role2"));
for (boolean b : results) {
    System.out.println(b);
}

使用者是yyt的時候,控制檯輸出的是:true,true,代表的是yyt擁有role1,role2這個角色
使用者是jack的時候,控制檯出去的是:true,false,代表的是jack使用者role1這個角色,但是沒有role2這個角色

1.3測試subject.hasAllRoles(List roles) 返回值是boolean

Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
//Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
System.out.println(subject.hasAllRoles(Arrays.asList("role1","role2"))?"有role2,role1這個角色":"role1,role2這個角色不全有");

使用者是yyt的時候,控制檯輸出的是:有role2,role1這個角色
使用者是jack的時候,控制檯出去的是:role1,role2這個角色不全有

1.4測試subject.checkRole(String roleName) 沒有返回值,假如驗證失敗,則會報錯:
org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

//Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
subject.checkRole("role2");

1.5測試subject.checkRoles(String… roleIdentifiers) 可以傳入多個角色名稱,假如驗證失敗,則會報錯:
org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
//Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
subject.checkRoles("role2","role1");

1.6測試subject.checkRoles(String… roleIdentifiers) 可以傳入多個角色名稱,假如驗證失敗,則會報錯:
org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
//Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
subject.checkRoles(Arrays.asList("role1","role2"));

2.基於許可權的控制
配置檔案內容如下:shiro-permission.ini

[users]
yyt=123,role1,role2
jack=1234,role1
[roles]
role1=user:create,user:update  
role2=user:create,user:delete

2.1測試subject.isPermitted(String name) 返回boolean

package com.kingsky;

import org.apache.shiro.subject.Subject;

public class TestPermission {
    public static void main(String[] args) {
        // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
        Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
        boolean result= subject.isPermitted("user:create");
        System.out.println(result?"有user:create這個許可權":"沒有user:create這個許可權");
    }
}

控制檯輸出:有user:create這個許可權,假如許可權名稱改為:user:delete則輸出的沒有這個許可權

2.2測試subject.isPermittedAll(String… names) 返回boolean,代表是全有或者不全有這些許可權

// Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
boolean result=subject.isPermittedAll("user:create","user:delete");
System.out.println(result?"有user:create,update這些許可權":"這些user:create,update許可權不全有");

控制檯輸出:有user:create,update這些許可權
假如修改許可權:user:delete,則會返回fase

2.3測試subject.isPermitted(String… names) 返回boolean[],對應的許可權是不是有

// Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
boolean results[]=subject.isPermitted("user:create","user:delete");
for (boolean b : results) {
    System.out.println(b);
}

控制檯輸出:true(代表user:create有許可權),false(代表user:delete沒有許可權)

2.4測試subject.checkPermission(String name);沒有返回值,但是驗證不成功則會報錯:
org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]

// Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
subject.checkPermission("user:delete");

2.5測試subject.checkPermissions(Stirng… names);沒有返回值,但是驗證不成功則會報錯:
org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]

// Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
subject.checkPermissions("user:create","user:update");

3.註解授權,jsp標籤授權
在JSP頁面通過相應的標籤完成:

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

4、Shiro對許可權字串缺失部分的處理
如“user:view”等價於“user:view:”;而“organization”等價於“organization:”或者“organization::”。可以這麼理解,這種方式實現了字首匹配。
另外如“user:”可以匹配如“user:delete”、“user:delete”可以匹配如“user:delete:1”、“user::1”可以匹配如“user:view:1”、“user”可以匹配“user:view”或“user:view:1”等。即可以匹配所有,不加可以進行字首匹配;但是如“:view”不能匹配“system:user:view”,需要使用“::view”,即字尾匹配必須指定字首(多個冒號就需要多個來匹配)。