Spring中集成Shiro授权实例

授权流程回顾

首先说一句,使用授权的前提当然是先要实现身份验证,也就是要保证用户登录之后才可能考虑授权的问题。关于身份验证之前已经写过了,还不清楚的童鞋可以点这里

上一篇文章介绍了Shiro中授权的一些基础知识和原理。学了就要用,本篇文章就介绍如何在项目中应用Shiro的授权。这里为了方便大家阅读,先贴出上一篇文章中分析出的授权流程:

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

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

接下来,用Permission和List进行匹配,其中遍历用户权限的匹配方法就是implies(…),这个单词可以理解成“蕴含”的意思,这样就比较好理解了。

由于各组件角色定位都很清楚,所以我们这里实现授权只需要实现AuthorizingRealm就可以了。那么Shiro是否有线程的AuthorizingRealm供我们使用呢?答案是肯定的。AuthorizingRealm的实现有:JdbcRealm、InitRealm、PropertiesRealm等。由于我决定将授权数据存在数据库中(大多数情况也应该是这样),所以这里使用JdbcRealm。注意:下文直接用细粒度的模式来实现授权(即用户到角色,角色关联到权限的方式)

准备工作

首先,我们要建两张表,,一张是用户到角色的关联表,一张的角色到权限的关联表。

首先是用户到角色的关联表 user_roles

id username role_name

然后是角色到权限关联表 roles_permissions

id role_name permission

配置Shiro

Shiro提供了两个可配置的SQL语句来取得某用户的所有权限:userRolesQuery和permissionsQuery,其中userRolesQuery是用来得到该用户的所有角色,而permissionsQuery是根据该用户的所有角色来取出所有的权限。这里我们配置的SQL为:

userRolesQuery= select role_name from user_roles where username = ?permissionsQuery = select permission from roles_permissions where role_name = ?

这也是Shiro提供的默认的SQL内容,由于我们表名和列名都是参照该SQL建立的,所以直接使用默认的SQL即可。

另外还有一点需要注意的是,JdbcRealm默认是不支持权限查找的,也就是permissionsQuery默认是不会执行的。需要配置permissionsLookupEnabled为true,才能使之生效。另外别忘了配置数据源datasource,下面贴上配置文件:

<bean id=”jdbcRealm” class=”org.apache.shiro.realm.jdbc.JdbcRealm”><=”credentialsMatcher”></property><property name=”authenticationQuery” value=”select password from user where username = ?”></property><=”dataSource”></property><property name=”permissionsLookupEnabled” value=”true”></property></bean>使用授权

配置好后就可以像上一篇文章里写的那样使用了: 比如我们在Controller中写一个方法

@RequiresPermissions(“news:view”)@RequestMapping(“/newsList”)public String newsList() {return “newsList”;}

当该用户没有news:view权限时,就会抛出UnauthorizedException异常,我们捕获该类异常并提供“未授权”页面返回给用户。在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;}}

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

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

放手后的微笑,只是用来掩盖疼痛的伤疤…

Spring中集成Shiro授权实例

相关文章:

你感兴趣的文章:

标签云: