Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证、授权、加密、会话管理、与Web集成、缓存等功能。
Shiro 权限配置一般使用的有两种,一种是采用注解的方式,在我们的 Controller 方法上,或者Action 方法上写入一些权限判断注解,具体怎么使用,我不做介绍,我主要推荐使用配置的方式。这也是我们现在要讲到的配置方式加载系统基础权限控制,采用对Url 进行控制。
一、Shiro配置文件配置方式
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/u/login.shtml" /> <property name="successUrl" value="/" /> <property name="unauthorizedUrl" value="/?login" /> <!-- 基本系统级别权限配置--> <property name="filterChainDefinitions" > <value> /page/login.jsp = anon <!-- 登录相关不拦截 --> /page/register/* = anon /page/index.jsp = authc /page/addItem* = authc,roles[数据管理员] /page/file* = authc,roleOR[普通用户,数据管理员] /page/listItems* = authc,roleOR[数据管理员,普通用户] /page/showItem* = authc,roleOR[数据管理员,普通用户] /page/updateItem*=authc,roles[数据管理员] /** = anon <!-- 其他不拦截 --> </value> </property> <!-- 自定义shiro 的 Filter --> <property name="filters"> <util:map> <entry key="login" value-ref="login"></entry> </util:map> </property></bean>
主要看上面的 filterChainDefinitions 部分,这里是配置我们的的url 和对应的Filter 关系配置。
重要:这里的加载顺序是自上而下,所以看到我们/** 写到最后,因为匹配不中最后都让这个匹配中。后面我们会讲到采用配置文件加载怎么有序加载。
二、Shiro filterChainDefinitions 中配置讲解
栗子1,带参数配置方式:
/admin/ask/editor.shtml = role[2008,2009]
上面配置的意义:就是在请求/admin/ask/editor.shtml 链接时候进入别名为 role 的Shiro Filter ,并且参数为数组[2008,2009] ,这里参数的意思是角色编号。具体这个参数怎么取,最下面的 5.2 点看代码。
栗子2,简单配置方式:
/admin/ask/editor.shtml = role
上面的配置意义: 就是在请求/admin/ask/editor.shtml 链接时候进入别名为 role 的Shiro Filter。
栗子3,多个Shiro Filter配置方式:
/admin/ask/editor.shtml = login,role[2008,2009]
上面配置意义: 就是在请求/admin/ask/editor.shtml 链接时候先进入 别名为 login 的Filter ,并且无参数。别名为login 的Filter 如果没通过,就不会走别名为role 的Filter ,如果别名为login 的Filter返回true ,则进入别名为role 的Filter 。也就是从前到后。
这样的场景是很正常的业务场景,就是先判断登录,再判断角色权限。
栗子4,Shiro Filter的执行顺序:
记住这句话, “ 自上而下,从左到右” 即可。如下代码:
/admin/ask/editor.shtml = login,role[2008,2009]/admin/ask/** = login,role[007]
如果来了一个链接为“/admin/ask/update.shtml ” ,先对比 /admin/ask/editor.shtml 是否匹配,如果匹配不中再走下面的通配/admin/ask/** 匹配中了后,再执行 login Filter ,然后通过login Filter 后再执行 role[007] Filter 。
所以记住一点,权限为金字塔状,先精确匹配或是权限稍小在前面,权限大(模糊匹配)的在后面。具体可以看栗子5.
栗子5,通配(模糊匹配):
/admin/ask/** = login,role[007]/admin/** = login,role[008]/** = login
上面是一个典型的金字塔式匹配方式,/** 是匹配所有,也就是如果上面的/admin/ask/** 和/admin/** 都匹配不中的时候,才走 /** = login 。如果反过来配置,如下:
/** = login/admin/** = login,role[008]/admin/ask/** = login,role[007]
这样配置的话,全部都走 /** = login了,下面的2个不可能会走。再看下面:
/admin/** = login,role[008]/admin/ask/** = login,role[007]/** = login
这样配置的话,那就永远都不会走 /admin/ask/**,因为都给 /admin/** 拦截了。
三、Shiro 的默认Filter 对应的类
四、自定义Shiro Filter 配置
定义Shiro Filter bean ,在 Spring 相关配置文件中配置。
<!-- 自定义Filter bean--><bean id="login" class="com.sojson.core.shiro.filter.LoginFilter"> <property name="customShiroSessionDAO" ref="customShiroSessionDAO"/></bean><bean id="role" class="com.sojson.core.shiro.filter.RoleFilter"/><bean id="permission" class="com.sojson.core.shiro.filter.PermissionFilter"/><bean id="simple" class="com.sojson.core.shiro.filter.SimpleAuthFilter"/>
定义Shiro Filter Bean 对应关系。
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- 省略配置,参考上面的代码 --><!-- 自定义shiro 的 Filter --><property name="filters"><util:map><!-- key 定义 Filter的别名,而 value-ref 对应上面bean的id --><entry key="login" value-ref="login"></entry><entry key="role" value-ref="role"></entry><entry key="simple" value-ref="simple"></entry><entry key="permission" value-ref="permission"></entry><entry key="kickout" value-ref="kickoutSessionFilter"></entry></util:map></property></bean>
这样就配置完成了。
五、自定义Shiro Filter
上面配置了Shiro Filter ,那下面举个栗子,然后以判断角色(role) 的Filter 的代码。
5.1 摘取配置文件中对Filter的配置:
/admin/ask/editor.shtml = role[2008,2009]
解释一下上面代码的意思,就是在请求/admin/ask/editor.shtml 链接时候进入别名为 role 的Shiro Filter ,并且参数为数组[2008,2009] ,这里参数的意思是角色编号。
5.2 Java代码,RoleFilter的定义:
package com.sojson.core.shiro.filter;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletResponse;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.StringUtils;import org.apache.shiro.web.filter.AccessControlFilter;import org.apache.shiro.web.util.WebUtils;/**** 开发公司:SOJSON在线工具 <p>* 版权所有:© www.sojson.com<p>* 博客地址:http://www.sojson.com/blog/ <p>* <p>** 角色判断校验** <p>** 区分 责任人 日期 说明<br/>* 创建 周柏成 2016年6月2日 <br/>** @author zhou-baicheng* @email so@sojson.com* @version 1.0,2016年6月2日 <br/>**/public class RoleFilter extends AccessControlFilter {static final String LOGIN_URL = "http://www.sojson.com/user/open/toLogin.shtml";static final String UNAUTHORIZED_URL = "http://www.sojson.com/unauthorized.html";@Overrideprotected boolean isAccessAllowed(ServletRequest request,ServletResponse response, Object mappedValue) throws Exception {//取到参数[2008,2009] ,强制转换判断。String[] arra = (String[])mappedValue;Subject subject = getSubject(request, response);for (String role : arra) {//判断是否有拥有当前权限,有则返回trueif(subject.hasRole("role:" + role)){return true;}}return false;}@Overrideprotected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception {Subject subject = getSubject(request, response);if (subject.getPrincipal() == null) {//表示没有登录,重定向到登录页面saveRequest(request);WebUtils.issueRedirect(request, response, LOGIN_URL);} else {if (StringUtils.hasText(UNAUTHORIZED_URL)) {//如果有未授权页面跳转过去WebUtils.issueRedirect(request, response, UNAUTHORIZED_URL);} else {//否则返回401未授权状态码WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);}}return false;}}
这样说的很清楚了吧。再有问题加群交流。
本文详细介绍了Shiro权限控制的配置方式,包括基于URL的权限控制、自定义Shiro Filter及其配置方法,并提供了角色判断Filter的具体实现。
2936

被折叠的 条评论
为什么被折叠?



