復(fù)習(xí)
什么是權(quán)限管理?
權(quán)限管理是系統(tǒng)的安全范濤, 要求必須是合法用戶(hù)才能訪問(wèn)系統(tǒng)(用戶(hù)認(rèn)證), 且必須具有該資源的訪問(wèn)權(quán)限才可以訪問(wèn)資源(授權(quán)).
認(rèn)證: 對(duì)用戶(hù)身份校驗(yàn),要求必須是合法用戶(hù)才能訪問(wèn)系統(tǒng).
授權(quán): 訪問(wèn)控制, 必須具有該資源的訪問(wèn)權(quán)限才能訪問(wèn)該資源.
權(quán)限模型: 標(biāo)準(zhǔn)權(quán)限數(shù)據(jù)模型包括:用戶(hù),角色,權(quán)限(包括資源和權(quán)限),用戶(hù)角色關(guān)系,角色權(quán)限關(guān)系.
權(quán)限分配: 用過(guò) UI 界面方便給用戶(hù)分配權(quán)限, 對(duì)上邊權(quán)限模型進(jìn)行增刪改查操作.
權(quán)限控制:
????基于角色的權(quán)限控制: 根據(jù)角色判斷是否有操作權(quán)限, 因?yàn)榻巧赡芤S時(shí)發(fā)生變化, 所以當(dāng)角色發(fā)生變化時(shí), 我們需要修改系統(tǒng)代碼. 這也就意味著系統(tǒng)可維護(hù)性不強(qiáng).
????基于組員的權(quán)限控制: 根據(jù)資源判斷是否有操作權(quán)限, 因?yàn)楫?dāng)我們開(kāi)發(fā)完系統(tǒng)后, 一些 URL 是很少發(fā)生變化的, 也就是說(shuō)不管角色怎么變化,這些 URL 是不變的,所以系統(tǒng)的可維護(hù)性強(qiáng).
權(quán)限管理的解決方案:
????對(duì)于粗顆粒權(quán)限管理,建議在系統(tǒng)的架構(gòu)層面解決.
比如當(dāng)我們用戶(hù)認(rèn)證后,獲取用戶(hù)的菜單, 不同的用戶(hù)有不同的菜單.也就是說(shuō)對(duì)資源進(jìn)行權(quán)限管理.
????對(duì)細(xì)顆粒權(quán)限管理,建議在系統(tǒng)業(yè)務(wù)層進(jìn)行處理.
比如當(dāng)我們要修改或刪除某條信息的時(shí)候, 不判斷是否有權(quán)限.
基于 URL 的權(quán)限管理(掌握):
????使用 web 應(yīng)用中filter 來(lái)實(shí)現(xiàn), 用戶(hù)請(qǐng)求 url, 通過(guò) filter 攔截,判斷用戶(hù)身份是否合法(用戶(hù)認(rèn)證), 再判斷請(qǐng)求地址是否是用戶(hù)權(quán)限范圍內(nèi)的 url(授權(quán)).
Shiro 授權(quán)流程
授權(quán)方式
Shiro 支持三種授權(quán)的權(quán)限:
編程式: 通過(guò)編寫(xiě) if/else 權(quán)限代碼塊完成
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
//有權(quán)限
} else {
//無(wú)權(quán)限
}
注解式: 通過(guò)在執(zhí)行的 Java 方法上放置相應(yīng)的注解完成
@RequiresRoles("admin")
public void hello(){
//有權(quán)限
}
jsp/GSP 標(biāo)簽:在 jsp/gsp 頁(yè)面通過(guò)相應(yīng)的標(biāo)簽完成
<shiro:hasRole name="admin">
<!-- 有權(quán)限 -->
</shiro:hasRole>
授權(quán)入門(mén)程序
** 創(chuàng)建 shiro-permission.ini 文件**
#用戶(hù)
[users]
#用戶(hù) zhang 密碼是123,此用戶(hù)具有role1和role2兩個(gè)角色
zhangsan=123,role1,role2
wang=123,role2
#角色
[roles]
# 角色role1對(duì)資源 user 用于 create 和 update 權(quán)限.
role1=user:create,user:update
role2=user:create,user:delete
role3=user:create
權(quán)限標(biāo)識(shí)符規(guī)則: 資源:操作:實(shí)例
例如user:create:01
表示對(duì)用戶(hù)資源的01實(shí)例進(jìn)行 create 操作.
例如user:create
表示對(duì)用戶(hù)資源進(jìn)行 create 操作.相當(dāng)于``user:create:*```
具體實(shí)現(xiàn)
// 角色授權(quán)幢妄、資源授權(quán)測(cè)試
@Test
public void testAuthorization() {
// 創(chuàng)建SecurityManager工廠
Factory<SecurityManager> factory = new IniSecurityManagerFactory(
"classpath:shiro-permission.ini");
// 創(chuàng)建SecurityManager
SecurityManager securityManager = factory.getInstance();
// 將SecurityManager設(shè)置到系統(tǒng)運(yùn)行環(huán)境,和spring后將SecurityManager配置spring容器中蘑辑,一般單例管理
SecurityUtils.setSecurityManager(securityManager);
// 創(chuàng)建subject
Subject subject = SecurityUtils.getSubject();
// 創(chuàng)建token令牌
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
"123");
// 執(zhí)行認(rèn)證
try {
subject.login(token);
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("認(rèn)證狀態(tài):" + subject.isAuthenticated());
// 認(rèn)證通過(guò)后執(zhí)行授權(quán)
// 基于角色的授權(quán)
// hasRole傳入角色標(biāo)識(shí)
boolean ishasRole = subject.hasRole("role1");
System.out.println("單個(gè)角色判斷" + ishasRole);
// hasAllRoles是否擁有多個(gè)角色
boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1",
"role2", "role3"));
System.out.println("多個(gè)角色判斷" + hasAllRoles);
// 使用check方法進(jìn)行授權(quán)券膀,如果授權(quán)不通過(guò)會(huì)拋出異常
// subject.checkRole("role13");
// 基于資源的授權(quán)
// isPermitted傳入權(quán)限標(biāo)識(shí)符
boolean isPermitted = subject.isPermitted("user:create:1");
System.out.println("單個(gè)權(quán)限判斷" + isPermitted);
boolean isPermittedAll = subject.isPermittedAll("user:create:1",
"user:delete");
System.out.println("多個(gè)權(quán)限判斷" + isPermittedAll);
// 使用check方法進(jìn)行授權(quán)爽撒,如果授權(quán)不通過(guò)會(huì)拋出異常
// subject.checkPermission("items:create:1");
}