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 標籤:在JSP/GSP 頁面通過相應的標籤完成:####
<shiro:hasRole name="admin">
<!— 有權限—>
</shiro:hasRole>
3.入門測試程序
測試分爲基於角色的權限控制和基於資源的權限控制(開發中建議使用)
1. 創建shiro-permission.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進行所有操作。
2. 測試代碼
public void testPermission(){
//根據ini文件創建SecurityManagerFactory
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
SecurityManager securityManager = factory.getInstance();
//將securityManager設置到運行環境中
SecurityUtils.setSecurityManager(securityManager);
//創建主體對象
Subject subject = SecurityUtils.getSubject();
//有身份和憑證信息生成一個token
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
boolean isAuthenticated = subject.isAuthenticated();
System.out.println("用戶認證狀態: "+isAuthenticated);
//基於角色的權限控制
boolean isHasRole1 = subject.hasRole("role1");
System.out.println("是否有role1角色: "+isHasRole1);
boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
System.out.println("是否有所有角色: "+hasAllRoles);
//使用check進行授權,如果授權失敗則拋異常
subject.checkRole("role1");
subject.checkRoles("role1","role2");
//基於資源的權限控制
boolean isPermitted = subject.isPermitted("user:create");
System.out.println("是否擁有該權限: "+isPermitted);
boolean isPermittedAll = subject.isPermittedAll("user:create:1","user:delete");
System.out.println("是否擁有所有的權限: "+isPermittedAll);
//使用check進行授權,如果授權失敗則拋異常
subject.checkPermission("user:create");
subject.checkPermissions("user:create","user:delete");
}
4.自定義realm
這裏用到的是基於資源的權限控制
1.在自定義realm完善doGetAuthorizationInfo()方法
// 授權
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//獲取身份信息
String principal = (String)principals.getPrimaryPrincipal();
//根據身份信息從數據庫中獲取權限數據
//使用靜態數據進行模擬...
List<String> permissions = new ArrayList<String>();
permissions.add("user:create");
permissions.add("user:delete");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//將權限數據封裝到SimpleAuthorizationInfo對象中
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
2.ini配置文件還使用認證階段使用的,不用改變。
[main]
#自定義realm
customRealm=com.ak.shiro.CustomRealm
#將realm設置到securityManager
securityManager.realms=$customRealm
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串有權限,否則 沒有權限,拋出異常。