SpringBoot:集成Shiro之INI授權(quán)篇

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)注騷棟.謝謝嘍~

Demo傳送門


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撵颊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惫叛,更是在濱河造成了極大的恐慌倡勇,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘉涌,死亡現(xiàn)場離奇詭異妻熊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仑最,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門扔役,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人警医,你說我怎么就攤上這事亿胸。” “怎么了预皇?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵侈玄,是天一觀的道長。 經(jīng)常有香客問我深啤,道長拗馒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任溯街,我火速辦了婚禮诱桂,結(jié)果婚禮上洋丐,老公的妹妹穿的比我還像新娘。我一直安慰自己挥等,他們只是感情好友绝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肝劲,像睡著了一般迁客。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辞槐,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天掷漱,我揣著相機(jī)與錄音,去河邊找鬼榄檬。 笑死卜范,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鹿榜。 我是一名探鬼主播海雪,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舱殿!你這毒婦竟也來了奥裸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤沪袭,失蹤者是張志新(化名)和其女友劉穎湾宙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枝恋,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡创倔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了焚碌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畦攘。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖十电,靈堂內(nèi)的尸體忽然破棺而出知押,到底是詐尸還是另有隱情,我是刑警寧澤鹃骂,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布台盯,位于F島的核電站,受9級特大地震影響畏线,放射性物質(zhì)發(fā)生泄漏静盅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一寝殴、第九天 我趴在偏房一處隱蔽的房頂上張望蒿叠。 院中可真熱鬧明垢,春花似錦、人聲如沸市咽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽施绎。三九已至溯革,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谷醉,已是汗流浹背致稀。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俱尼,地道東北人豺裆。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像号显,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子躺酒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容