Shiro源码分析(十二)——鉴权流程

2021SC@SDUSC

一.Demo代码

这是在shiro源码的quickstart目录下有QuickStart.java文件,截取了其中鉴权部分的代码。

		// 测试一个角色:
		// 判断当前用户的角色是否为schwartz
        if (currentUser.hasRole("schwartz")) { // 1
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        // 测试类型化权限(而不是实例级)
        // 判断当前用户是否被允许使用lightsaber执行wield动作
        if (currentUser.isPermitted("lightsaber:wield")) { // 2
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        // 实例级权限:
        // 判断当前用户是否被允许驾驶牌照为eagle5的winnebago
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

二.源码分析

本文针对鉴权中的isPermitted()方法进行分析

2

public class DelegatingSubject implements Subject {
	// 如果允许此Subject执行操作或访问由指定权限字符串汇总的资源,则返回true。
	// 这是对应类型安全的Permission变量的重载方法。
    public boolean isPermitted(String permission) {
    	// hasPrincipals()方法已经在上一篇文章中分析过
        return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
    }
}

public class ModularRealmAuthorizer implements Authorizer, PermissionResolverAware, RolePermissionResolverAware {
    public boolean isPermitted(PrincipalCollection principals, String permission) {
    	// 确保Realm是配置好的
        assertRealmsConfigured();
        for (Realm realm : getRealms()) {
            if (!(realm instanceof Authorizer)) continue;
            if (((Authorizer) realm).isPermitted(principals, permission)) {
                return true;
            }
        }
        return false;
    }
}

public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager {
    public boolean isPermitted(PrincipalCollection principals, String permissionString) {
        return this.authorizer.isPermitted(principals, permissionString);
    }
}

public abstract class AuthorizingRealm extends AuthenticatingRealm
        implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
    public boolean isPermitted(PrincipalCollection principals, String permission) {
    	// 获取权限解析器,利用权限解析器的resolvePermission()方法解析字符串形式的权限
    	// 2.1 -> getPermissionResolver()
    	// 2.2 -> resolvePermission()
        Permission p = getPermissionResolver().resolvePermission(permission);
        return isPermitted(principals, p); // 2.3
    }
}

2.1

PermissionResolver解析字符串值并将其转换为Permission实例。
默认的WildcardPermissionResolver应该适用于大多数目的,它构造了WildcardPermission对象。
但是,如果应用程序希望使用不同的Permission实现,可以配置任何解析器。
PermissionResolver被许多Shiro组件使用,比如注释、属性文件配置、URL配置等。
当指定了权限的String表示形式,并且在执行安全检查之前需要将String转换为permission实例时,此方法非常有用。
Shiro默认在几乎所有组件中都支持通配符权限,我们以WildcardPermissionResolver的形式来实现。
WildcardPermissions默认支持的一个优点是,它使得在数据库中存储复杂的权限变得非常容易——也使得在JSP文件、注释等中表示权限变得非常容易,在这些文件中,简单的字符串表示非常有用。
虽然这恰好是Shiro的默认值,但你当然可以通过向Shiro组件提供该接口的任何实例来提供自定义的String-to-Permission转换。

public abstract class AuthorizingRealm extends AuthenticatingRealm
        implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
    public PermissionResolver getPermissionResolver() {
        return permissionResolver;
    }
}

2.2

WildcardPermission是一个非常灵活的权限构造,支持多级权限匹配。但一般会遵循下面解释的一些标准约定。
在最简单的形式中,WildcardPermission可以用作简单的权限字符串。可以授予用户一个“editNewsletter”权限,然后通过调用检查用户是否拥有editNewsletter权限。
subject.isPermitted("editNewsletter")
这整体相当于:
subject.isPermitted( new WildcardPermission("editNewsletter") )
简单的权限字符串可能适用于简单的应用程序,但它要求你拥有“viewNewsletter”,“deleteNewsletter”,“createNewsletter”等权限。您还可以使用通配符为用户授予“*”权限(赋予该类名称),这意味着它们拥有所有权限。但是使用这种方法,就不能说一个用户拥有“所有通讯权限”。出于这个原因,WildcardPermission支持多级权限。

public interface PermissionResolver {
	// 根据给定的字符串表示形式解析Permission。
    Permission resolvePermission(String permissionString);
}

// PermissionResolver实现,它根据输入字符串返回一个新的通配符权限。
public class WildcardPermissionResolver implements PermissionResolver {
	// 返回基于指定的permissionString构造的新的WildcardPermission实例。
    public Permission resolvePermission(String permissionString) {
        return new WildcardPermission(permissionString, caseSensitive);
    }
}

2.3

本方法和上一篇文章中掉用的方法是一致的。

public abstract class AuthorizingRealm extends AuthenticatingRealm
        implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
    public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        AuthorizationInfo info = getAuthorizationInfo(principals);
        return isPermitted(permission, info);
    }
}

(完)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值