1 shiro授權
1.1 授權流程
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 標籤:在JSP/GSP頁面通過相應的標籤完成:
<shiro:hasRole name="admin">
<!— 有權限—>
</shiro:hasRole>
本教程序授權測試使用第一種編程方式,實際與web系統集成使用後兩種方式。
1.3 授權測試
1.3.1 shiro-permission.ini
創建存放權限的配置文件shiro-permission.ini,如下:
[html] view plain copy print?
[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
在ini文件中用戶、角色、權限的配置規則是:“用戶名=密碼,角色1,角色2...” “角色=權限1,權限2...”,首先根據用戶名找角色,再根據角色找權限,角色是權限集合。
1.3.2 權限字符串規則
權限字符串的規則是:“資源標識符:操作:資源實例標識符”,意思是對哪個資源的哪個實例具有什麼操作,“:”是資源/操作/實例的分割符,權限字符串也可以使用*通配符。
例子:
用戶創建權限:user:create,或user:create:*
用戶修改實例001的權限:user:update:001
用戶實例001的所有權限:user:*:001
1.3.3 測試代碼
測試代碼同認證代碼,注意ini地址改爲shiro-permission.ini,主要學習下邊授權的方法,注意:在用戶認證通過後執行下邊的授權代碼。
[java] view plain copy print?
@Test
public void testPermission() {
// 從ini文件中創建SecurityManager工廠
Factory<SecurityManager> factory = new IniSecurityManagerFactory(
"classpath:shiro-permission.ini");
// 創建SecurityManager
SecurityManager securityManager = factory.getInstance();
// 將securityManager設置到運行環境
SecurityUtils.setSecurityManager(securityManager);
// 創建主體對象
Subject subject = SecurityUtils.getSubject();
// 對主體對象進行認證
// 用戶登陸
// 設置用戶認證的身份(principals)和憑證(credentials)
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
try {
subject.login(token);
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 用戶認證狀態
Boolean isAuthenticated = subject.isAuthenticated();
System.out.println("用戶認證狀態:" + isAuthenticated);
// 用戶授權檢測 基於角色授權
// 是否有某一個角色
System.out.println("用戶是否擁有一個角色:" + subject.hasRole("role1"));
// 是否有多個角色
System.out.println("用戶是否擁有多個角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));
//subject.checkRole("role1");
//subject.checkRoles(Arrays.asList("role1", "role2"));
// 授權檢測,失敗則拋出異常
// subject.checkRole("role22");
// 基於資源授權
System.out.println("是否擁有某一個權限:" + subject.isPermitted("user:delete"));
System.out.println("是否擁有多個權限:" + subject.isPermittedAll("user:create:1","user:delete"));
//檢查權限
subject.checkPermission("sys:user:delete");
subject.checkPermissions("user:create:1","user:delete");
}
1.3.4 基於角色的授權
[java] view plain copy print?
// 用戶授權檢測 基於角色授權
// 是否有某一個角色
System.out.println("用戶是否擁有一個角色:" + subject.hasRole("role1"));
// 是否有多個角色
System.out.println("用戶是否擁有多個角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));
對應的check方法:
subject.checkRole("role1");
subject.checkRoles(Arrays.asList("role1","role2"));
上邊check方法如果授權失敗則拋出異常:
[java] view plain copy print?
org.apache.shiro.authz.UnauthorizedException: Subject does not have role [.....]
1.3.5 基於資源授權
[java] view plain copy print?
// 基於資源授權
System.out.println("是否擁有某一個權限:" + subject.isPermitted("user:delete"));
System.out.println("是否擁有多個權限:" + subject.isPermittedAll("user:create:1","user:delete"));
對應的check方法:
subject.checkPermission("sys:user:delete");
subject.checkPermissions("user:create:1","user:delete");
上邊check方法如果授權失敗則拋出異常:
[java] view plain copy print?
org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [....]
1.4 自定義realm
與上邊認證自定義realm一樣,大部分情況是要從數據庫獲取權限數據,這裏直接實現基於資源的授權。
1.4.1 realm代碼
在認證章節寫的自定義realm類中完善doGetAuthorizationInfo方法,此方法需要完成:根據用戶身份信息從數據庫查詢權限字符串,由shiro進行授權。
[java] view plain copy print?
// 授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
// 獲取身份信息
String username = (String) principals.getPrimaryPrincipal();
// 根據身份信息從數據庫中查詢權限數據
//....這裏使用靜態數據模擬
List<String> permissions = new ArrayList<String>();
permissions.add("user:create");
permissions.add("user.delete");
//將權限信息封閉爲AuthorizationInfo
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for(String permission:permissions){
simpleAuthorizationInfo.addStringPermission(permission);
}
return simpleAuthorizationInfo;
}
1.4.2 shiro-realm.ini
ini配置文件還使用認證階段使用的,不用改變。
1.4.3 測試代碼
同上邊的授權測試代碼,注意修改ini地址爲shiro-realm.ini。
1.4.4 授權執行流程
1、 執行subject.isPermitted("user:create")
2、 securityManager通過ModularRealmAuthorizer進行授權
3、 ModularRealmAuthorizer調用realm獲取權限信息
4、ModularRealmAuthorizer再通過permissionResolver解析權限字符串,校驗是否匹配