Shiro简单授权原理分析

Shiro授权简介

Shiro授权简单来说分为两种类型:

粗粒度的:也就是代码中直接写入和角色的绑定。细粒度的:代码中写入的是和权限的绑定,而角色到权限和可配置的。

对于粗粒度来说,若角色对应权限有改变的话,那么则需要更改代码,很不方便。而细粒度的好处显而易见,,所以一般项目中应该都采用细粒度的权限配置。

源码及流程分析

那么Shiro中是如何来完成权限检验的呢? 通过调用Subject.hasRoles(…)或Subject.isPermitted(…) 另外还有Subject.checkRoles(…)或Subject.checkPermissions(…) 前两种和后两种的区别是,后两种在没有权限时会抛出异常。

关于角色,相信你都会定义,因为就是一个名字,比如admin、vip、user等。 而对于权限的定义,就需要有一套规则了。在Shiro中我们可以这么来定义权限字符串:资源标识符:操作:对象实例ID。另外这里支持通配符配置, 比如: user:create表示对user有create的权限(这里省略了:对象实例ID,等价于user:create:*) user:*表示对user拥有所有操作的权限(create,update,delete,view) user:view:1表示对user的1实例有view的权限 差不多就类似这样,就不多说了。Shiro内部会有一个PermissionResolver来负责将这类字符串解析为Permission对象。

下面分析一下授权的流程:

(String roleIdentifier, AuthorizationInfo info) {return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);}

而对于Subject.isPermitted(…)稍微会显得复杂一些,前三步都一样,就是AuthorizingRealm对于判断isPermitted的逻辑稍微有点不一样。它会先将权限字符串转换成Permission,将用户的权限转换成List<Permission>,这里的List<Permission>由三个部分组成:

而JdbcRealm的实现是使用了stringPermissions,可能第一想法以为它是用了RolePermissionResolver吧。 好了,接下来,用Permission和List进行匹配,其中遍历用户权限的匹配方法就是implies(…),这个单词可以理解成“蕴含”的意思,这样就比较好理解了。

(Permission permission, AuthorizationInfo info) {Collection<Permission> perms = getPermissions(info);if (perms != null && !perms.isEmpty()) {for (Permission perm : perms) {if (perm.implies(permission)) {return true;}}}return false;}

举个例子,比如user:*权限impliesuser:create权限,这就是一种蕴含关系。

具体用法

一般有编程式和声明式两种:

编程式:Subject subject = SecurityUtils.getSubject();if(subject.hasRole(“admin”)) {//有权限} else {//无权限}声明式:@RequiresRoles(“admin”)() {//有权限}

没有权限的话就抛出相应的异常。而我们只需要捕获异常做出相应的处理就可以了,在Spring中是可以配置一个全局的ExceptionHandler的。当然在Spring3.2之后的版本还提供了@ControllerAdvice来增强Controller,其中定义的所有@ExceptionHandler方法将会应用于所有的@RequestMapping方法,那么我们可以这么来定义异常处理类:

{@ExceptionHandler( { UnauthorizedException.class })@ResponseStatus(HttpStatus.UNAUTHORIZED)public ModelAndView processUnauthorizedException(NativeWebRequest request, UnauthorizedException e) {ModelAndView mv = new ModelAndView();mv.addObject(“contextPath”, request.getContextPath());mv.addObject(“exception”, e);mv.setViewName(“special/unauthorized”);return mv;}}

当然对于编程式的也可以直接使用subject.checkRoles(“admin”),这样一来也会抛出异常并被ExceptionHandler捕获了。

这里若启用声明式的鉴权,还需要启用aspectJ自动代理,并支持对类的代理。

<aop:aspectj-autoproxy proxy-target-class=”true” /><bean class=”org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor”><=”securityManager” /></bean>

下一篇文章会写一个Spring项目中整合JdbcRealm来实现鉴权的实例。

,再回头,便生出无限羁绊。那是彼此的刺在对方心里留下的痕迹,

Shiro简单授权原理分析

相关文章:

你感兴趣的文章:

标签云: