带你揭秘Shiro(二)

授权流程

1、对subject进行授权,调用方法isPermitted("permission串")

2、SecurityManager执行授权,通过ModularRealmAuthorizer执行授权

3、ModularRealmAuthorizer执行realm(自定义的Realm)从数据库查询权限数据,调用realm的doGetAuthorizationInfo授权方法

4、realm从数据库查询权限数据,返回ModularRealmAuthorizer

5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对

6、如果比对后,isPermitted中"permission串"在realm查询到权限数据中,说明用户访问permission串有权限,否则 没有权限,抛出异常。

修改之前realmDemo.java中的doGetAuthorizationInfo方法
// 用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
        PrincipalCollection principals) {

    // 从 principals获取主身份信息
    // 将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
    String userName = (String) principals.getPrimaryPrincipal();

    // 根据身份信息获取权限信息
    // 连接数据库...
    // 模拟从数据库获取到数据
    List<String> permissions = new ArrayList<String>();
    permissions.add("user:create");// 用户的创建
    permissions.add("user:update");// 用户的修改
    // ....

    // 查到权限数据,返回授权信息(要包括 上边的permissions)
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    // 将上边查询到授权信息填充到simpleAuthorizationInfo对象中
    simpleAuthorizationInfo.addStringPermissions(permissions);

    return simpleAuthorizationInfo;
}
3.创建shiro-realm.ini文件,配置自定义的realm,将realm设置到securityManager中,因为之前已经配置过,该步骤可以省略

4.在AuthorizationDemo中添加方法进行测试
// 自定义realm进行资源授权测试
@Test
public void testRealmDemo() {

    // 创建SecurityManager工厂
    Factory<SecurityManager> factory = new IniSecurityManagerFactory(
            "classpath:shiro-realm.ini");

    // 创建SecurityManager

    SecurityManager securityManager = factory.getInstance();

    // 将SecurityManager设置到系统运行环境,和spring后将SecurityManager配置spring容器中,一般单例管理
    SecurityUtils.setSecurityManager(securityManager);

    // 创建subject
    Subject subject = SecurityUtils.getSubject();

    // 创建token令牌
    UsernamePasswordToken token = new UsernamePasswordToken("jack", "123");

    // 执行认证
    try {
        subject.login(token);
    } catch (AuthenticationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println("认证状态:" + subject.isAuthenticated());
    // 认证通过后执行授权

    // 基于资源的授权,调用isPermitted方法会调用realmDemo从数据库查询正确权限数据

    // isPermitted传入权限标识符,判断user:create:1是否在realmDemo查询到权限数据之内
    boolean isPermitted = subject.isPermitted("user:create:1");
    System.out.println("单个权限判断" + isPermitted);



    boolean isPermittedAll = subject.isPermittedAll("user:create:1","user:update");
    System.out.println("多个权限判断" + isPermittedAll);

    // 使用check方法进行授权,如果授权不通过会抛出异常
    // subject.checkPermission("user:delete");
}