INI文件授權(quán)方式簡單易懂,但是由于是硬編碼,所以在可維護(hù)性上差強(qiáng)人意.自己酌情使用.
前言
前面說到如何使用INI文件進(jìn)行登錄認(rèn)證,但是這一篇博客主要講的是Shiro的另外一個重要功能就是授權(quán)操作,這里簡單說明一下,授權(quán)操作就是來定義合法用戶的權(quán)限操作.這一篇我們?nèi)匀皇褂?strong>INI文件的形式,看一下,我們?nèi)绾蝸磉M(jìn)行授權(quán)操作.
RBAC簡單闡述
基于角色的權(quán)限訪問控制(Role-Based Access Control)作為傳統(tǒng)訪問控制(自主訪問含末,強(qiáng)制訪問)的有前景的代替受到廣泛的關(guān)注。在RBAC中,權(quán)限與角色相關(guān)聯(lián),用戶通過成為適當(dāng)角色的成員而得到這些角色的權(quán)限嘱支。這就極大地簡化了權(quán)限的管理。在一個組織中摹量,角色是為了完成各種工作而創(chuàng)造勃痴,用戶則依據(jù)它的責(zé)任和資格來被指派相應(yīng)的角色,用戶可以很容易地從一個角色被指派到另一個角色洗搂。角色可依新的需求和系統(tǒng)的合并而賦予新的權(quán)限消返,而權(quán)限也可根據(jù)需要而從某角色中回收。角色與角色的關(guān)系可以建立起來以囊括更廣泛的客觀情況耘拇。(選自百度百科.)
上面所說的可以用一句話來簡單闡述什么樣的用戶是怎樣的角色.擁有什么的權(quán)限.在Shiro的授權(quán)方面就是遵循這一規(guī)則.下面我們就基于前面的一篇博客Shiro認(rèn)證篇來編寫我們的授權(quán)代碼.來看一下使用INI文件如何實現(xiàn)用戶授權(quán)的.
編寫INI文件,實現(xiàn)授權(quán)
上一篇博客中我們的INI文件,定義了用戶名稱以及密碼,如下所示.
[users]
root=123456
admin=admin
下面我們來分不同情況說一下我們?nèi)绾谓o用戶添加角色和權(quán)限.
- 最常見的就是某個用戶擁有一個角色和一種權(quán)限,假設(shè)root是role1角色.擁有權(quán)限permission1.那么,在INI文件中我們首先要編寫[roles]標(biāo)簽,和[users]標(biāo)簽類似.然后我們添加用戶的角色以及標(biāo)簽,代碼如下所示.
[users]
root=123456,role1
[roles]
roles = permission1
- 那么,一個用戶是否可以擁有多個角色和多個權(quán)限呢?答案是肯定的,下面我就直接舉例說明了,假設(shè)admin用戶是role1,role2角色.同時,role2角色擁有permission2和permission3的權(quán)限,那么綜合第一種情況,我們就可以如下編寫代碼.
[users]
root=123456,role1
admin=admin,role1,role2
[roles]
role1 = permission1
role2 = permission2,permission3
查詢用戶是否擁有角色
上面我們編寫了什么樣的用戶對應(yīng)什么樣的角色和權(quán)限(其實已經(jīng)完成了授權(quán)的操作),下面我們來看一下如何查詢某個用戶是否擁有某個角色.當(dāng)然了,這個操作必須要在用戶已經(jīng)登錄認(rèn)證完成之后才能進(jìn)行操作.我們首先把我們所需要的三個認(rèn)證方法.具體方法和使用情景如下所示.
hasRole用于單一角色判斷,參數(shù)為角色名稱,返回值類型是布爾值.true表示擁有該角色,false表示未擁有該角色.
boolean hasRole(String var1);
hasAllRoles用于判斷是否擁有某些角色,參數(shù)為角色數(shù)組,返回值類型是布爾值.true表示全部擁有,false表示未全部擁有.
boolean hasAllRoles(Collection<String> var1);
hasRoles用于判斷是否擁有某些角色,,參數(shù)為角色數(shù)組,返回值是布爾值的數(shù)組.
boolean[] hasRoles(List<String> var1);
現(xiàn)在我們就接著上一篇文章中的MyShiro來進(jìn)行一下邏輯代碼的編寫,MyShiro中的原始代碼如下所示.
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;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyShiro {
public Map<String,Object> userLoginAction (String userName,String passWord){
Map<String,Object> resultMap = new HashMap<>();
//初始化SecurityManager對象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//通過SecurityManager工廠對象,獲取SecurityManager實例對象.
SecurityManager securityManager = factory.getInstance();
// 把 securityManager 實例 綁定到 SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
//組建Subject主體.
Subject subject = SecurityUtils.getSubject();
//創(chuàng)建 token 令牌
UsernamePasswordToken token = new UsernamePasswordToken(userName,passWord);
//用戶登錄操作.
try{
subject.login(token);
resultMap.put("code","200");
resultMap.put("msg","用戶登錄成功");
}catch (AuthenticationException e){
//登錄失敗原因 1 用戶不存在 2 用戶密碼不正確
resultMap.put("code","-1");
resultMap.put("msg","用戶登錄失敗");
}
return resultMap;
}
}
由于,用戶必須通過認(rèn)證操作,所以在登錄失敗的情況下我們無法進(jìn)行角色的判斷.我們只能在用戶登錄成功的情況下進(jìn)行角色是否含有的操作.所以我們就只在try成功的情況下進(jìn)行驗證操作.如下圖所示.
代碼比較簡單,我就直接把三個方法直接使用進(jìn)行代碼的編寫.如下所示.
//用戶登錄操作.
try{
subject.login(token);
resultMap.put("code","200");
resultMap.put("msg","用戶登錄成功");
if (subject.hasRole("role1")){
resultMap.put("roleMsg1","用戶擁有角色1");
}else {
resultMap.put("roleMsg1","用戶未擁有角色1");
}
if (subject.hasAllRoles(Arrays.asList("role1","role2"))){
resultMap.put("roleMsg2","用戶同時擁有角色1和角色2");
}else {
resultMap.put("roleMsg2","用戶未同時擁有角色1和角色2");
}
//這里就不返回第三種方法了,直接打印了
System.out.println(Arrays.asList(subject.hasRoles(Arrays.asList("role1","role2"))));
}catch (AuthenticationException e){
//登錄失敗原因 1 用戶不存在 2 用戶密碼不正確
resultMap.put("code","-1");
resultMap.put("msg","用戶登錄失敗");
}
我們啟動下程序,然后使用接口登錄一下查看是否正確.驗證結(jié)果如下所示.
- 用戶 root
- 用戶 admin
查詢用戶是否擁有權(quán)限
查詢用戶是否含有某種權(quán)限的大致過程和用戶是否含有某種角色的大致過程是大體相同的.方法如下所示.
boolean isPermitted(String var1);
boolean isPermittedAll(String... var1);
boolean[] isPermitted(String... var1);
具體實現(xiàn)代碼如下所示.
if (subject.isPermitted("permission1")){
resultMap.put("PermittedMsg1","用戶擁有權(quán)限1");
}else {
resultMap.put("PermittedMsg1","用戶未擁有權(quán)限1");
}
if (subject.isPermittedAll("permission2","permission3")){
resultMap.put("PermittedMsg2","用戶同時擁有權(quán)限1和權(quán)限2");
}else {
resultMap.put("PermittedMsg2","用戶未同時擁有權(quán)限1和權(quán)限2");
}
接下來我們依然驗證正確性,然后使用接口登錄一下查看是否正確.驗證結(jié)果如下所示.
- 用戶 root
- 用戶 admin
結(jié)語
本篇集成Shiro之INI授權(quán)篇到此就結(jié)束了,這里做一個簡單的總結(jié),使用INI文件的方式雖然簡單,但是由于使用硬編碼的方式,所以可維護(hù)性比較差,大家酌情使用! 好了,今天就到這里了.如果有任何問題歡迎在評論區(qū)留言.希望大家繼續(xù)關(guān)注騷棟.謝謝嘍~