shiro授权实例

一、shiro授权角色实例

1、需要导入的依赖

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

2、新建配置文件shiro.ini

[users]
sumu=123456,role1,role2
sumu1=123456,role1

;其中sumu表示用户名,123456 表示密码 ,role1等表示用户

3、使用测试

private void login(String configFile,String name ,String pass) {
        //1、获取SecurityManager工厂,此处使用Ini配置文件初始化
        Factory<SecurityManager> factory = new IniSecurityManagerFactory(configFile);
        //2、得到SecurityManager实例 并绑定给SecurityUtils
        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
        subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(name, pass);
        subject.login(token);
    }

public Subject subject()
    {
        return subject;
    }   
@Test(expected = UnauthorizedException.class)
    public void testCheckRole() {
        login("classpath:shiro-role.ini", "sumu", "123456");
        //断言拥有角色:role1
        subject().checkRole("role1");
        //断言拥有角色:role1 and role3 失败抛出异常
        subject().checkRoles("role1", "role3");
    }

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

二、权限分配实例

1、修改配置文件

  • 文件名:shiro-promission.ini
[users]
zhang=123,role1,role2
wang=123,role1
[roles]
role1=user:create,user:update,user:view
role2=user:create,user:delete

2、使用测试

  • 其中的Login,Subject方法和上个实例一样。
 @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"));
        //判断没有权限:user:view
        Assert.assertTrue(subject().isPermitted("user:view"));
    }

三、授权的流程

授权流程

在这里插入图片描述

流程如下:

  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 表示授权失败。

ModularRealmAuthorizer 进行多 Realm 匹配流程:

  • 首先检查相应的 Realm 是否实现了实现了 Authorizer;
  • 如果实现了 Authorizer,那么接着调用其相应的 isPermitted*/hasRole* 接口进行匹配;
  • 如果有一个 Realm 匹配那么将返回 true,否则返回 false。

如果 Realm 进行授权的话,应该继承 AuthorizingRealm,其流程是:

  • 如果调用 hasRole*,则直接获取 AuthorizationInfo.getRoles() 与传入的角色比较即可;首先如果调用如 isPermitted(“user:view”),首先通过 PermissionResolver 将权限字符串转换成相应的 Permission 实例,默认使用 WildcardPermissionResolver,即转换为通配符的 WildcardPermission;
  • 通过 AuthorizationInfo.getObjectPermissions() 得到 Permission 实例集合;通过 AuthorizationInfo.getStringPermissions() 得到字符串集合并通过 PermissionResolver 解析为 Permission 实例;然后获取用户的角色,并通过 RolePermissionResolver 解析角色对应的权限集合(默认没有实现,可以自己提供);
  • 接着调用 Permission.implies(Permission p) 逐个与传入的权限比较,如果有匹配的则返回 true,否则 false。

Q.E.D.