【Shiro学习之三】权限验证

Apache shiro:1.6.0

一、重要组件
1、Authorizer 的职责是进行授权(访问控制),是 Shiro API 中授权核心的入口点,其提供了相应的角色/权限判断接口,具体协调realm验证权限是在ModularRealmAuthorizer里进行。

2、PermissionResolver接口用于解析权限字符串到WildcardPermission实例,默认实现WildcardPermissionResolver;RolePermissionResolver接口用于根据角色解析相应的权限集合。

3、AuthorizationInfo

public interface AuthorizationInfo extends Serializable { 
    Collection<String> getRoles(); //获取角色字符串信息 
    Collection<String> getStringPermissions(); //获取权限字符串信息 
    Collection<Permission> getObjectPermissions(); //获取 Permission 对象信息 
} 

AuthorizationInfo 用于聚合授权信息的,当我们使用AuthorizingRealm 时, 如果身份验证成功, 在进行授权时就通过doGetAuthorizationInfo 方法获取角色/权限信息用于授权验证。
Shiro提供了一个实现 SimpleAuthorizationInfo,大多数时候使用这个即可

二、权限验证流程
1、代码示例
(1)角色验证

@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]);
    }

(2)权限验证

@Test
    public void testIsPermitted() {
        login("classpath:shiro-permission.ini", "zhang", "123");
        //判断拥有权限:user:create
        Assert.assertTrue(subject().isPermitted("user:create"));
        //判断拥有权限:user:update and user:delete
        Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete"));
        //判断没有权限:user:view
        Assert.assertFalse(subject().isPermitted("user:view"));
    }

2、图示流程

流程如下: 
(1)首先调用Subject.isPermitted*/hasRole*接口,其会委托给 SecurityManager,而SecurityManager 接着会委托给 Authorizer; 
(2)Authorizer 是真正的授权者,如果我们调用如 isPermitted(“user:view”),其首先会通过PermissionResolver 把字符串转换成相应的 Permission 实例; 
(3)在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限; 
(4)Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会委托给ModularRealmAuthorizer 进行循环判断,如果匹配如 isPermitted*/hasRole*会返回 true,否则返回 false 表示授权失败。 

3、源码流程分析

角色验证:

Subject::hasRole
-->DelegatingSubject::hasRole
-->securityManager::hasRole
-->AuthorizingSecurityManager::hasRole
-->ModularRealmAuthorizer::hasRole
在这里会获取所有的realm,调用realm的doGetAuthorizationInfo进行获取权限信息AuthorizationInfo
-->然后AuthorizationInfo调用getRoles()获取所有角看是否包含指定的角色;
ModularRealmAuthorizer 进行多 Realm 匹配流程: 
(1)首先检查相应的Realm是否实现了实现了 Authorizer; 
(2)如果实现了Authorizer,那么接着调用其相应的isPermitted*/hasRole*接口进行匹配; 
(3)如果有一个Realm匹配那么将返回true 否则返回 false

权限验证:

Subject::isPermitted
-->DelegatingSubject::isPermitted
-->securityManager::isPermitted
-->AuthorizingSecurityManager::isPermitted
-->ModularRealmAuthorizer::isPermitted
-->AuthorizingRealm::isPermitted
首先通过 PermissionResolver 将权限字符串转换成相应的 Permission 实例,默认使用 WildcardPermissionResolver,即转换为通配符的WildcardPermission;
然后和realm的doGetAuthorizationInfo获取的权限信息AuthorizationInfo,获得所有权限集合,然后循环比对。

 

posted @ 2020-10-15 15:13  cac2020  阅读(442)  评论(0编辑  收藏  举报