欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

第三章 授權(quán)——《跟我學(xué)Shiro》

系統(tǒng) 1815 0

?

目錄貼: ?跟我學(xué)Shiro目錄貼

?

授權(quán),也叫訪問控制,即在應(yīng)用中控制誰(shuí)能訪問哪些資源(如訪問頁(yè)面/編輯數(shù)據(jù)/頁(yè)面操作等)。在授權(quán)中需了解的幾個(gè)關(guān)鍵對(duì)象:主體(Subject)、資源(Resource)、權(quán)限(Permission)、角色(Role)。

主體

主體,即訪問應(yīng)用的用戶,在Shiro中使用Subject代表該用戶。用戶只有授權(quán)后才允許訪問相應(yīng)的資源。

資源

在應(yīng)用中用戶可以訪問的任何東西,比如訪問JSP頁(yè)面、查看/編輯某些數(shù)據(jù)、訪問某個(gè)業(yè)務(wù)方法、打印文本等等都是資源。用戶只要授權(quán)后才能訪問。

權(quán)限

安全策略中的原子授權(quán)單位,通過權(quán)限我們可以表示在應(yīng)用中用戶有沒有操作某個(gè)資源的權(quán)力。即權(quán)限表示在應(yīng)用中用戶能不能訪問某個(gè)資源,如:

訪問用戶列表頁(yè)面

查看/新增/修改/刪除用戶數(shù)據(jù)(即很多時(shí)候都是CRUD(增查改刪)式權(quán)限控制)

打印文檔等等。。。

?

如上可以看出,權(quán)限代表了用戶有沒有操作某個(gè)資源的權(quán)利,即反映在某個(gè)資源上的操作允不允許,不反映誰(shuí)去執(zhí)行這個(gè)操作。所以后續(xù)還需要把權(quán)限賦予給用戶,即定義哪個(gè)用戶允許在某個(gè)資源上做什么操作(權(quán)限),Shiro不會(huì)去做這件事情,而是由實(shí)現(xiàn)人員提供。

?

Shiro支持粗粒度權(quán)限(如用戶模塊的所有權(quán)限)和細(xì)粒度權(quán)限(操作某個(gè)用戶的權(quán)限,即實(shí)例級(jí)別的),后續(xù)部分介紹。

角色

角色代表了操作集合,可以理解為權(quán)限的集合,一般情況下我們會(huì)賦予用戶角色而不是權(quán)限,即這樣用戶可以擁有一組權(quán)限,賦予權(quán)限時(shí)比較方便。典型的如:項(xiàng)目經(jīng)理、技術(shù)總監(jiān)、CTO、開發(fā)工程師等都是角色,不同的角色擁有一組不同的權(quán)限。

隱式角色 :即直接通過角色來(lái)驗(yàn)證用戶有沒有操作權(quán)限,如在應(yīng)用中CTO、技術(shù)總監(jiān)、開發(fā)工程師可以使用打印機(jī),假設(shè)某天不允許開發(fā)工程師使用打印機(jī),此時(shí)需要從應(yīng)用中刪除相應(yīng)代碼;再如在應(yīng)用中CTO、技術(shù)總監(jiān)可以查看用戶、查看權(quán)限;突然有一天不允許技術(shù)總監(jiān)查看用戶、查看權(quán)限了,需要在相關(guān)代碼中把技術(shù)總監(jiān)角色從判斷邏輯中刪除掉;即粒度是以角色為單位進(jìn)行訪問控制的,粒度較粗;如果進(jìn)行修改可能造成多處代碼修改。

顯示角色 :在程序中通過權(quán)限控制誰(shuí)能訪問某個(gè)資源,角色聚合一組權(quán)限集合;這樣假設(shè)哪個(gè)角色不能訪問某個(gè)資源,只需要從角色代表的權(quán)限集合中移除即可;無(wú)須修改多處代碼;即粒度是以資源/實(shí)例為單位的;粒度較細(xì)。

?

?

請(qǐng)google搜索“RBAC”和“RBAC新解”分別了解“基于角色的訪問控制”“基于資源的訪問控制(Resource-Based Access Control)”。

?

3.1?授權(quán)方式

Shiro支持三種方式的授權(quán):

?

編程式:通過寫if/else授權(quán)代碼塊完成:?

      Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
    //有權(quán)限
} else {
    //無(wú)權(quán)限
}?
    

?

注解式:通過在執(zhí)行的Java方法上放置相應(yīng)的注解完成:?

      @RequiresRoles("admin")
public void hello() {
    //有權(quán)限
}?
    

沒有權(quán)限將拋出相應(yīng)的異常;

?

JSP/GSP標(biāo)簽:在JSP/GSP頁(yè)面通過相應(yīng)的標(biāo)簽完成:?

      <shiro:hasRole name="admin">
<!— 有權(quán)限 —>
</shiro:hasRole>?
    

后續(xù)部分將詳細(xì)介紹如何使用。? ?

?

3.2?授權(quán)

基于角色的訪問控制(隱式角色)

?

1、在ini配置文件配置用戶擁有的角色(shiro-role.ini)?

      [users]
zhang=123,role1,role2
wang=123,role1?
    

規(guī)則即:“用戶名=密碼,角色1,角色2”,如果需要在應(yīng)用中判斷用戶是否有相應(yīng)角色,就需要在相應(yīng)的Realm中返回角色信息,也就是說(shuō)Shiro不負(fù)責(zé)維護(hù)用戶-角色信息,需要應(yīng)用提供,Shiro只是提供相應(yīng)的接口方便驗(yàn)證,后續(xù)會(huì)介紹如何動(dòng)態(tài)的獲取用戶角色。

?

2、測(cè)試用例(com.github.zhangkaitao.shiro.chapter3.RoleTest)?

          @Test
    public void testHasRole() {
        login("classpath:shiro-role.ini", "zhang", "123");
        //判斷擁有角色:role1
        Assert.assertTrue(subject().hasRole("role1"));
        //判斷擁有角色:role1 and role2
        Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2")));
        //判斷擁有角色:role1 and role2 and !role3
        boolean[] result = subject().hasRoles(Arrays.asList("role1", "role2", "role3"));
        Assert.assertEquals(true, result[0]);
        Assert.assertEquals(true, result[1]);
        Assert.assertEquals(false, result[2]);
    }?
    

Shiro提供了hasRole/hasRole用于判斷用戶是否擁有某個(gè)角色/某些權(quán)限;但是沒有提供如hashAnyRole用于判斷是否有某些權(quán)限中的某一個(gè)。?

?

          @Test(expected = UnauthorizedException.class)
    public void testCheckRole() {
        login("classpath:shiro-role.ini", "zhang", "123");
        //斷言擁有角色:role1
        subject().checkRole("role1");
        //斷言擁有角色:role1 and role3 失敗拋出異常
        subject().checkRoles("role1", "role3");
    }?
    

Shiro提供的checkRole/checkRoles和hasRole/hasAllRoles不同的地方是它在判斷為假的情況下會(huì)拋出UnauthorizedException異常。

?

到此基于角色的訪問控制(即隱式角色)就完成了,這種方式的缺點(diǎn)就是如果很多地方進(jìn)行了角色判斷,但是有一天不需要了那么就需要修改相應(yīng)代碼把所有相關(guān)的地方進(jìn)行刪除;這就是粗粒度造成的問題。

?

基于資源的訪問控制(顯示角色)

1、在ini配置文件配置用戶擁有的角色及角色-權(quán)限關(guān)系(shiro-permission.ini)?

      [users]
zhang=123,role1,role2
wang=123,role1
[roles]
role1=user:create,user:update
role2=user:create,user:delete?
    

規(guī)則:“用戶名=密碼,角色1,角色2”“角色=權(quán)限1,權(quán)限2”,即首先根據(jù)用戶名找到角色,然后根據(jù)角色再找到權(quán)限;即角色是權(quán)限集合;Shiro同樣不進(jìn)行權(quán)限的維護(hù),需要我們通過Realm返回相應(yīng)的權(quán)限信息。只需要維護(hù)“用戶——角色”之間的關(guān)系即可。

?

2、測(cè)試用例(com.github.zhangkaitao.shiro.chapter3.PermissionTest)? ???

          @Test
    public void testIsPermitted() {
        login("classpath:shiro-permission.ini", "zhang", "123");
        //判斷擁有權(quán)限:user:create
        Assert.assertTrue(subject().isPermitted("user:create"));
        //判斷擁有權(quán)限:user:update and user:delete
        Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete"));
        //判斷沒有權(quán)限:user:view
        Assert.assertFalse(subject().isPermitted("user:view"));
    }?
    

Shiro提供了isPermitted和isPermittedAll用于判斷用戶是否擁有某個(gè)權(quán)限或所有權(quán)限,也沒有提供如isPermittedAny用于判斷擁有某一個(gè)權(quán)限的接口。

?

          @Test(expected = UnauthorizedException.class)
    public void testCheckPermission () {
        login("classpath:shiro-permission.ini", "zhang", "123");
        //斷言擁有權(quán)限:user:create
        subject().checkPermission("user:create");
        //斷言擁有權(quán)限:user:delete and user:update
        subject().checkPermissions("user:delete", "user:update");
        //斷言擁有權(quán)限:user:view 失敗拋出異常
        subject().checkPermissions("user:view");
    }?
    

但是失敗的情況下會(huì)拋出UnauthorizedException異常。

?

到此基于資源的訪問控制(顯示角色)就完成了,也可以叫基于權(quán)限的訪問控制,這種方式的一般規(guī)則是“資源標(biāo)識(shí)符:操作”,即是資源級(jí)別的粒度;這種方式的好處就是如果要修改基本都是一個(gè)資源級(jí)別的修改,不會(huì)對(duì)其他模塊代碼產(chǎn)生影響,粒度小。但是實(shí)現(xiàn)起來(lái)可能稍微復(fù)雜點(diǎn),需要維護(hù)“用戶——角色,角色——權(quán)限(資源:操作)”之間的關(guān)系。??

?

3.3 Permission

字符串通配符權(quán)限

規(guī)則:“資源標(biāo)識(shí)符:操作:對(duì)象實(shí)例ID”??即對(duì)哪個(gè)資源的哪個(gè)實(shí)例可以進(jìn)行什么操作。其默認(rèn)支持通配符權(quán)限字符串,“:”表示資源/操作/實(shí)例的分割;“,”表示操作的分割;“*”表示任意資源/操作/實(shí)例。

??

1 、單個(gè)資源單個(gè)權(quán)限 ?

      subject().checkPermissions("system:user:update");
    

用戶擁有資源“system:user”的“update”權(quán)限。

?

2 、單個(gè)資源多個(gè)權(quán)限

ini配置文件?

      role41=system:user:update,system:user:delete
    

然后通過如下代碼判斷

      subject().checkPermissions("system:user:update", "system:user:delete");
    

用戶擁有資源“system:user”的“update”和“delete”權(quán)限。如上可以簡(jiǎn)寫成:

?

ini配置(表示角色4擁有system:user資源的update和delete權(quán)限)? ?

      role42="system:user:update,delete" ?
    

?接著可以通過如下代碼判斷?

      subject().checkPermissions("system:user:update,delete");
    

通過“system:user:update,delete”驗(yàn)證"system:user:update, system:user:delete"是沒問題的,但是反過來(lái)是規(guī)則不成立。

?

3 、單個(gè)資源全部權(quán)限

ini配置?

      role51="system:user:create,update,delete,view"
    

然后通過如下代碼判斷?

      subject().checkPermissions("system:user:create,delete,update:view");
    

用戶擁有資源“system:user”的“create”、“update”、“delete”和“view”所有權(quán)限。如上可以簡(jiǎn)寫成:

?

ini配置文件(表示角色5擁有system:user的所有權(quán)限)

      role52=system:user:*
    

也可以簡(jiǎn)寫為(推薦上邊的寫法):

      role53=system:user
    

然后通過如下代碼判斷

      subject().checkPermissions("system:user:*");
subject().checkPermissions("system:user");?
    

通過“system:user:*”驗(yàn)證“system:user:create,delete,update:view”可以,但是反過來(lái)是不成立的。

?

4 、所有資源全部權(quán)限

ini配置?

      role61=*:view
    

然后通過如下代碼判斷

      subject().checkPermissions("user:view");
    

用戶擁有所有資源的“view”所有權(quán)限。假設(shè)判斷的權(quán)限是“"system:user:view”,那么需要“role5=*:*:view”這樣寫才行。

?

5 、實(shí)例級(jí)別的權(quán)限

5.1 、單個(gè)實(shí)例單個(gè)權(quán)限

ini配置

      role71=user:view:1
    

對(duì)資源user的1實(shí)例擁有view權(quán)限。

然后通過如下代碼判斷?

      subject().checkPermissions("user:view:1");
    

?

5.2 、單個(gè)實(shí)例多個(gè)權(quán)限

ini配置? ? ? ? ? ?

      role72="user:update,delete:1"
    

對(duì)資源user的1實(shí)例擁有update、delete權(quán)限。

然后通過如下代碼判斷

      subject().checkPermissions("user:delete,update:1");
subject().checkPermissions("user:update:1", "user:delete:1");?
    

??

5.3 、單個(gè)實(shí)例所有權(quán)限

ini配置 ?

      role73=user:*:1
    

對(duì)資源user的1實(shí)例擁有所有權(quán)限。

然后通過如下代碼判斷?

      subject().checkPermissions("user:update:1", "user:delete:1", "user:view:1");
    

? ?

5.4 、所有實(shí)例單個(gè)權(quán)限

ini配置?

      role74=user:auth:*
    

對(duì)資源user的1實(shí)例擁有所有權(quán)限。

然后通過如下代碼判斷?

      subject().checkPermissions("user:auth:1", "user:auth:2");
    

??

5.5 、所有實(shí)例所有權(quán)限

ini配置?

      role75=user:*:*
    

對(duì)資源user的1實(shí)例擁有所有權(quán)限。

然后通過如下代碼判斷? ???

      subject().checkPermissions("user:view:1", "user:auth:2");
    

??

6 、Shiro 對(duì)權(quán)限字符串缺失部分的處理

如“user:view”等價(jià)于“user:view:*”;而“organization”等價(jià)于“organization:*”或者“organization:*:*”。可以這么理解,這種方式實(shí)現(xiàn)了前綴匹配。

另外如“user:*”可以匹配如“user:delete”、“user:delete”可以匹配如“user:delete:1”、“user:*:1”可以匹配如“user:view:1”、“user”可以匹配“user:view”或“user:view:1”等。即*可以匹配所有,不加*可以進(jìn)行前綴匹配;但是如“*:view”不能匹配“system:user:view”,需要使用“*:*:view”,即后綴匹配必須指定前綴(多個(gè)冒號(hào)就需要多個(gè)*來(lái)匹配)。

?

7 、WildcardPermission

如下兩種方式是等價(jià)的:??

      subject().checkPermission("menu:view:1");
subject().checkPermission(new WildcardPermission("menu:view:1"));?
    

因此沒什么必要的話使用字符串更方便。

?

8 、性能問題

通配符匹配方式比字符串相等匹配來(lái)說(shuō)是更復(fù)雜的,因此需要花費(fèi)更長(zhǎng)時(shí)間,但是一般系統(tǒng)的權(quán)限不會(huì)太多,且可以配合緩存來(lái)提供其性能,如果這樣性能還達(dá)不到要求我們可以實(shí)現(xiàn)位操作算法實(shí)現(xiàn)性能更好的權(quán)限匹配。另外實(shí)例級(jí)別的權(quán)限驗(yàn)證如果數(shù)據(jù)量太大也不建議使用,可能造成查詢權(quán)限及匹配變慢。可以考慮比如在sql查詢時(shí)加上權(quán)限字符串之類的方式在查詢時(shí)就完成了權(quán)限匹配。?

?

3.4?授權(quán)流程


第三章 授權(quán)——《跟我學(xué)Shiro》

流程如下:

1、首先調(diào)用Subject.isPermitted*/hasRole*接口,其會(huì)委托給SecurityManager,而SecurityManager接著會(huì)委托給Authorizer;

2、Authorizer是真正的授權(quán)者,如果我們調(diào)用如isPermitted(“user:view”),其首先會(huì)通過PermissionResolver把字符串轉(zhuǎn)換成相應(yīng)的Permission實(shí)例;

3、在進(jìn)行授權(quán)之前,其會(huì)調(diào)用相應(yīng)的Realm獲取Subject相應(yīng)的角色/權(quán)限用于匹配傳入的角色/權(quán)限;

4、Authorizer會(huì)判斷Realm的角色/權(quán)限是否和傳入的匹配,如果有多個(gè)Realm,會(huì)委托給ModularRealmAuthorizer進(jìn)行循環(huán)判斷,如果匹配如isPermitted*/hasRole*會(huì)返回true,否則返回false表示授權(quán)失敗。

?

ModularRealmAuthorizer進(jìn)行多Realm匹配流程:

1、首先檢查相應(yīng)的Realm是否實(shí)現(xiàn)了實(shí)現(xiàn)了Authorizer;

2、如果實(shí)現(xiàn)了Authorizer,那么接著調(diào)用其相應(yīng)的isPermitted*/hasRole*接口進(jìn)行匹配;

3、如果有一個(gè)Realm匹配那么將返回true,否則返回false。

?

如果Realm進(jìn)行授權(quán)的話,應(yīng)該繼承AuthorizingRealm,其流程是:

1.1、如果調(diào)用hasRole*,則直接獲取AuthorizationInfo.getRoles()與傳入的角色比較即可;

1.2、首先如果調(diào)用如isPermitted(“user:view”),首先通過PermissionResolver將權(quán)限字符串轉(zhuǎn)換成相應(yīng)的Permission實(shí)例,默認(rèn)使用WildcardPermissionResolver,即轉(zhuǎn)換為通配符的WildcardPermission;

2、通過AuthorizationInfo.getObjectPermissions()得到Permission實(shí)例集合;通過AuthorizationInfo. getStringPermissions()得到字符串集合并通過PermissionResolver解析為Permission實(shí)例;然后獲取用戶的角色,并通過RolePermissionResolver解析角色對(duì)應(yīng)的權(quán)限集合(默認(rèn)沒有實(shí)現(xiàn),可以自己提供);

3、接著調(diào)用Permission. implies(Permission p)逐個(gè)與傳入的權(quán)限比較,如果有匹配的則返回true,否則false。?

?

3.5 Authorizer、PermissionResolver及RolePermissionResolver

Authorizer的職責(zé)是進(jìn)行授權(quán)(訪問控制),是Shiro API中授權(quán)核心的入口點(diǎn),其提供了相應(yīng)的角色/權(quán)限判斷接口,具體請(qǐng)參考其Javadoc。SecurityManager繼承了Authorizer接口,且提供了ModularRealmAuthorizer用于多Realm時(shí)的授權(quán)匹配。PermissionResolver用于解析權(quán)限字符串到Permission實(shí)例,而RolePermissionResolver用于根據(jù)角色解析相應(yīng)的權(quán)限集合。

?

我們可以通過如下ini配置更改Authorizer實(shí)現(xiàn):?

      authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
securityManager.authorizer=$authorizer?
    

對(duì)于ModularRealmAuthorizer,相應(yīng)的AuthorizingSecurityManager會(huì)在初始化完成后自動(dòng)將相應(yīng)的realm設(shè)置進(jìn)去,我們也可以通過調(diào)用其setRealms()方法進(jìn)行設(shè)置。對(duì)于實(shí)現(xiàn)自己的authorizer可以參考ModularRealmAuthorizer實(shí)現(xiàn)即可,在此就不提供示例了。

?

設(shè)置ModularRealmAuthorizer的permissionResolver,其會(huì)自動(dòng)設(shè)置到相應(yīng)的Realm上(其實(shí)現(xiàn)了PermissionResolverAware接口),如:

      permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
authorizer.permissionResolver=$permissionResolver?
    

?

設(shè)置ModularRealmAuthorizer的rolePermissionResolver,其會(huì)自動(dòng)設(shè)置到相應(yīng)的Realm上(其實(shí)現(xiàn)了RolePermissionResolverAware接口),如:

      rolePermissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver?
    

?

示例

1 、ini 配置(shiro-authorizer.ini ????

      [main]
#自定義authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
#自定義permissionResolver
#permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
permissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.BitAndWildPermissionResolver
authorizer.permissionResolver=$permissionResolver
#自定義rolePermissionResolver
rolePermissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver

securityManager.authorizer=$authorizer

    
      #自定義realm 一定要放在securityManager.authorizer賦值之后(因?yàn)檎{(diào)用setRealms會(huì)將realms設(shè)置給authorizer,并給各個(gè)Realm設(shè)置permissionResolver和rolePermissionResolver)
realm=com.github.zhangkaitao.shiro.chapter3.realm.MyRealm
securityManager.realms=$realm?
    

設(shè)置securityManager?的realms一定要放到最后,因?yàn)樵谡{(diào)用SecurityManager.setRealms時(shí)會(huì)將realms設(shè)置給authorizer,并為各個(gè)Realm設(shè)置permissionResolver和rolePermissionResolver。另外,不能使用IniSecurityManagerFactory創(chuàng)建的IniRealm,因?yàn)槠涑跏蓟樞虻膯栴}可能造成后續(xù)的初始化Permission造成影響。

?

2 、定義BitAndWildPermissionResolver 及BitPermission

BitPermission用于實(shí)現(xiàn)位移方式的權(quán)限,如規(guī)則是:

權(quán)限字符串格式:+資源字符串+權(quán)限位+實(shí)例ID;以+開頭中間通過+分割;權(quán)限:0?表示所有權(quán)限;1?新增(二進(jìn)制:0001)、2?修改(二進(jìn)制:0010)、4?刪除(二進(jìn)制:0100)、8?查看(二進(jìn)制:1000);如?+user+10?表示對(duì)資源user擁有修改/查看權(quán)限。

      public class BitPermission implements Permission {
    private String resourceIdentify;
    private int permissionBit;
    private String instanceId;
    public BitPermission(String permissionString) {
        String[] array = permissionString.split("\\+");
        if(array.length > 1) {
            resourceIdentify = array[1];
        }
        if(StringUtils.isEmpty(resourceIdentify)) {
            resourceIdentify = "*";
        }
        if(array.length > 2) {
            permissionBit = Integer.valueOf(array[2]);
        }
        if(array.length > 3) {
            instanceId = array[3];
        }
        if(StringUtils.isEmpty(instanceId)) {
            instanceId = "*";
        }
    }

    @Override
    public boolean implies(Permission p) {
        if(!(p instanceof BitPermission)) {
            return false;
        }
        BitPermission other = (BitPermission) p;
        if(!("*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify))) {
            return false;
        }
        if(!(this.permissionBit ==0 || (this.permissionBit & other.permissionBit) != 0)) {
            return false;
        }
        if(!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) {
            return false;
        }
        return true;
    }
}?
    

Permission接口提供了boolean implies(Permission p)方法用于判斷權(quán)限匹配的;

      public class BitAndWildPermissionResolver implements PermissionResolver {
    @Override
    public Permission resolvePermission(String permissionString) {
        if(permissionString.startsWith("+")) {
            return new BitPermission(permissionString);
        }
        return new WildcardPermission(permissionString);
    }
}?
    

BitAndWildPermissionResolver實(shí)現(xiàn)了PermissionResolver接口,并根據(jù)權(quán)限字符串是否以“+”開頭來(lái)解析權(quán)限字符串為BitPermission或WildcardPermission。

?

3 、定義MyRolePermissionResolver

RolePermissionResolver用于根據(jù)角色字符串來(lái)解析得到權(quán)限集合。

      public class MyRolePermissionResolver implements RolePermissionResolver {
    @Override
    public Collection<Permission> resolvePermissionsInRole(String roleString) {
        if("role1".equals(roleString)) {
            return Arrays.asList((Permission)new WildcardPermission("menu:*"));
        }
        return null;
    }
}?
    

此處的實(shí)現(xiàn)很簡(jiǎn)單,如果用戶擁有role1,那么就返回一個(gè)“menu:*”的權(quán)限。

?

4 、自定義Realm

      public class MyRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRole("role1");
        authorizationInfo.addRole("role2");
        authorizationInfo.addObjectPermission(new BitPermission("+user1+10"));
        authorizationInfo.addObjectPermission(new WildcardPermission("user1:*"));
        authorizationInfo.addStringPermission("+user2+10");
        authorizationInfo.addStringPermission("user2:*");
        return authorizationInfo;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //和com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1. getAuthenticationInfo代碼一樣,省略
}
}?
    

此時(shí)我們繼承AuthorizingRealm而不是實(shí)現(xiàn)Realm接口;推薦使用AuthorizingRealm,因?yàn)椋?

AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token):表示獲取身份驗(yàn)證信息;

AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals):表示根據(jù)用戶身份獲取授權(quán)信息。

這種方式的好處是當(dāng)只需要身份驗(yàn)證時(shí)只需要獲取身份驗(yàn)證信息而不需要獲取授權(quán)信息。對(duì)于AuthenticationInfo和AuthorizationInfo請(qǐng)參考其Javadoc獲取相關(guān)接口信息。

?

另外我們可以使用JdbcRealm,需要做的操作如下:

1、執(zhí)行sql/ shiro-init-data.sql?插入相關(guān)的權(quán)限數(shù)據(jù);

2、使用shiro-jdbc-authorizer.ini配置文件,需要設(shè)置jdbcRealm.permissionsLookupEnabled

為true來(lái)開啟權(quán)限查詢。

?

此次還要注意就是不能把我們自定義的如“+user1+10”配置到INI配置文件,即使有IniRealm完成,因?yàn)镮niRealm在new完成后就會(huì)解析這些權(quán)限字符串,默認(rèn)使用了WildcardPermissionResolver完成,即此處是一個(gè)設(shè)計(jì)權(quán)限,如果采用生命周期(如使用初始化方法)的方式進(jìn)行加載就可以解決我們自定義permissionResolver的問題。

?

5 、測(cè)試用例

      public class AuthorizerTest extends BaseTest {

    @Test
    public void testIsPermitted() {
        login("classpath:shiro-authorizer.ini", "zhang", "123");
        //判斷擁有權(quán)限:user:create
        Assert.assertTrue(subject().isPermitted("user1:update"));
        Assert.assertTrue(subject().isPermitted("user2:update"));
        //通過二進(jìn)制位的方式表示權(quán)限
        Assert.assertTrue(subject().isPermitted("+user1+2"));//新增權(quán)限
        Assert.assertTrue(subject().isPermitted("+user1+8"));//查看權(quán)限
        Assert.assertTrue(subject().isPermitted("+user2+10"));//新增及查看

        Assert.assertFalse(subject().isPermitted("+user1+4"));//沒有刪除權(quán)限

        Assert.assertTrue(subject().isPermitted("menu:view"));//通過MyRolePermissionResolver解析得到的權(quán)限
    }
}?
    

通過如上步驟可以實(shí)現(xiàn)自定義權(quán)限驗(yàn)證了。另外因?yàn)椴恢С謍asAnyRole/isPermittedAny這種方式的授權(quán),可以參考我的一篇《簡(jiǎn)單shiro擴(kuò)展實(shí)現(xiàn)NOT、AND、OR權(quán)限驗(yàn)證?》進(jìn)行簡(jiǎn)單的擴(kuò)展完成這個(gè)需求,在這篇文章中通過重寫AuthorizingRealm里的驗(yàn)證邏輯實(shí)現(xiàn)的。? ? ? ?

?

示例源代碼: https://github.com/zhangkaitao/shiro-example ;可加群134755960探討Spring/Shiro技術(shù)。

第三章 授權(quán)——《跟我學(xué)Shiro》


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 91精品国产一区二区三区蜜臀 | 请吃饭的姐姐 | 免费视频日韩 | 亚洲精品免费在线观看 | 色亚洲色图 | 91精品国产爱久久久久 | 国产成人精品福利网站在线观看 | 国产成人精品久久二区二区91 | 成人精品久久久 | 日本特级黄色录像 | 国产免费资源 | 国产高清一区 | 久久97精品久久久久久久看片 | 日韩在线高清 | 人人看人人看 | 亚洲视频在线看 | 国产精品拍拍拍福利在线观看 | 嫩草影院在线免费观看 | 这里只有精品视频 | 欧美日韩亚洲一区二区三区在线观看 | 三级色视频| 免费高清欧美一区二区视频 | 一区二区三区成人A片在线观看 | 欧美高潮| 欧美一级毛片在线播放 | 秋霞影院精品久久久久 | 日韩成人免费视频 | 国产成人自拍一区 | 国产午夜大片 | 成人理论 | 国产91精品黄网在线观看 | 超碰人人在线 | a国产精品 | 欧美激情 亚洲 | 偷拍自拍亚洲 | 清纯唯美亚洲综合激情 | 香港三级日本三级韩国a | 国产精品一区二区三区99 | 国产欧美日韩精品a在线观看高清 | 黄视频欧美| 久久五月婷 |