Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证、授权、加密、会话管理、与Web集成、缓存等功能。
Shiro 权限配置一般使用的有两种,一种是采用注解的方式,在我们的Controller 方法上,或者Action方法上写入一些权限判断注解,具体怎么使用,我不做介绍,我主要推荐使用配置的方式。这也是我们现在要讲到的配置方式加载系统基础权限控制,采用对Url进行控制。
`
`
`
`
`
``
`
`
`/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 `
``
``
``
`
`
`
``
``
``
主要看上面的?`filterChainDefinitions`部分,这里是配置我们的的`url`和对应的`Filter`关系配置。
**重要:**这里的加载顺序是自上而下,所以看到我们/** 写到最后,因为匹配不中最后都让这个匹配中。后面我们会讲到采用配置文件加载怎么有序加载。
二、Shiro filterChainDefinitions 中配置讲解栗子1,带参数配置方式:/admin/ask/editor.shtml = role[2008,2009]上面配置的意义:就是在请求/admin/ask/editor.shtml链接时候进入别名为role的Shiro Filter,并且参数为数组[2008,2009],这里参数的意思是角色编号。具体这个参数怎么取,最下面的 5.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。也就是从前到后。
这样的场景是很正常的业务场景,就是先判断登录,再判断角色权限。
记住这句话, “ 自上而下,从左到右” 即可。如下代码:
`/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/**拦截了。
Filter名称
类路径(点击可以进入官方介绍,强烈建议看看)
anon
?org.apache.shiro.web.filter.authc.AnonymousFilter
authc
org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic
?org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout
org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation
org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms
org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port
org.apache.shiro.web.filter.authz.PortFilter
rest
org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles
org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl
org.apache.shiro.web.filter.authz.SslFilter
user
org.apache.shiro.web.filter.authc.UserFilter
定义Shiro Filter bean,在Spring 相关配置文件中配置。
```` ` ```` `` `` `定义`Shiro Filter 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在线工具
* 版权所有:? www.sojson.com
* 博客地址:http://www.sojson.com/blog/
*
*
* 角色判断校验
*
*
*
* 区分 责任人 日期 说明
* 创建 周柏成 2016年6月2日
*
* @author zhou-baicheng
* @email so@sojson.com
* @version 1.0,2016年6月2日
*
*/
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";
@Override
protected 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) {
//判断是否有拥有当前权限,有则返回true
if(subject.hasRole("role:" + role)){
return true;
}
}
return false;
}
@Override
protected 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;
}
}
这样说的很清楚了吧。再有问题加群交流。