shiro 拦截器自定义拦截后怎么加角色

shiro(15)
Shiro 学习笔记(5)—— 自定义角色权限解析器
执行授权代码的前提
我们首先要明确的一个知识点是,什么时候 Shiro 才会去执行权限匹配的代码呢?
(1)在我们的 Realm 的实现类中,必须要有关于 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)
方法的实现;
(2)在调用 Shiro 的认证成功以后的 isPermitted() 方法或者
checkPermission() 方法的时候。这一点很容易看出,当我们检查权限的时候,就会去执行授权的逻辑。
自定义权限解析规的步骤
步骤1:实现 Permission 接口
在这个接口中实现权限匹配的方法。
public class MyPermission implements Permission {
private String resourceId;
private String instanceId;
public MyPermission(){
public MyPermission(String permissionStr){
String[] strs = permissionStr.split("\\+");
if(strs.length&1){
this.resourceId = strs[1];
if(this.resourceId == null || "".equals(this.resourceId)){
this.resourceId = "*";
if(strs.length&2){
this.operator = strs[2];
if(strs.length&3){
this.instanceId = strs[3];
if(this.instanceId == null || "".equals(this.instanceId)){
this.instanceId = "*";
System.out.println("实例化 MyPermission 时 =& " + this.toString());
* 【这是一个非常重要的方法】
* 由程序员自己编写授权是否匹配的逻辑,
* 我们这里的实现,是将 Realm 中给出的 Permission 和 ini 配置中指定的 PermissionResoler 中指定的 Permission 进行比对
* 比对的规则完全由我们自己定义
* permission
public boolean implies(Permission permission) {
if(!(permission instanceof MyPermission)){
return false;
MyPermission mp = (MyPermission)
if(!"*".equals(mp.resourceId) && !this.resourceId.equals(mp.resourceId)){
return false;
if(!"*".equals(mp.operator) && !this.operator.equals(mp.operator)){
return false;
if(!"*".equals(mp.instanceId) && !this.instanceId.equals(mp.instanceId)){
return false;
return true;
public String toString() {
return "MyPermission{" +
"resourceId='" + resourceId + '\'' +
", operator='" + operator + '\'' +
", instanceId='" + instanceId + '\'' +
步骤2:实现 PermissionResolver 接口
实现 PermissionResolver 接口的意义在于告诉 Shiro 根据字符串的表现形式(表现特征),采用什么样的 Permission 进行匹配。
public class MyPermissionResolver implements PermissionResolver{
public Permission resolvePermission(String s) {
if(s.startsWith("+")){
return new MyPermission(s);
return new WildcardPermission(s);
说明:这段代码实现的一个效果是:如果我们的权限字符串是以 “+” 号开头的话,就使用我们自定义的 MyPermission ,否则就使用默认的 WildcardPermission 解析这个字符串。
步骤3:实现授权的逻辑
这里,我们还是使用刚刚用的 StaticRealm 去实现授权操作,代码:
public class MyStaticRealm extends AuthorizingRealm {
* 用于授权
* principalCollection
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("static Realm 中授权的方法");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole("r1");
info.addRole("r2");
info.addStringPermission("+user+");
info.addObjectPermission(new MyPermission("+user+add+1"));
* 用于认证
* AuthenticationException
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
步骤 4:在 shiro.ini 文件中增加配置
permissionResolver=com.liwei.permission.MyPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer
详细说明代码执行流程
代码其实就是上面的样子,但是光这么讲很抽象,此时权限匹配的过程是定义在我们实现的 Permission 接口的 implies() 方法中。所以我们还要详细介绍 Shiro 在进行权限匹配的流程:
1、首先调用 Subject.isPermitted() 接口,其会委托给 SecurityManager,而 SecurityManager 接着会委托给 Authorizer;
2、Authorizer 是真正的授权者,
如果我们调用如 isPermitted(“user:view”),其首先会通过 PermissionResolver 把字符串转换成相应的 Permission 实例。下面我们说明这个实例是如何转换的呢?
根据我们在 shiro.ini 文件中配置的
permissionResolver=com.liwei.permission.MyPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer
此时 Shiro 会去这个配置文件中指定的 PermissionResolver 找相应的实现类 MyPermissionResolver ,通过“user:view”这个字符串去实现类中找到对应应该使用的 Permission 实现类,然后实例化一个 Permission 对象(这个 Permission 对象很重要,我们暂时把它记住,下一步马上就要用来做匹配)。
3、在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限;
这个转换实例的过程就是在代码中通过在 Realm 中实现的 doGetAuthorizationInfo() 方法里写的 info.addObjectPermission(new MyPermission(“+user+add+1”));
即构造函数实现的,在这个过程中也实例化了一个 Permission 对象,用于和上一步的 Permission 对象进行比较,这个比较的过程是通过我们实现 Permission 接口中的 implies() 方法来定义的 。
如果权限的字符串表示是一个集合,那么 implies() 方法可能会被执行多次,直到该方法返回 ‘true’ 为止。
4、Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会委托给 ModularRealmAuthorizer 进行循环判断,如果匹配,那么 isPermitted*/hasRole* 会返回 true,否则返回 false ,表示授权验证失败。
自定义角色匹配器
下面继续说明如何自定义角色匹配,其实过程和自定义权限匹配是类似的,但是我们要明确一点,因为角色是一组权限的集合,所以我们指定角色解析器的时候,须要告诉 Shiro 使用什么 Permission 。
步骤1:实现 RolePermissionResolver
public class MyRolePermissionResolver implements RolePermissionResolver {
public Collection&Permission& resolvePermissionsInRole(String s) {
if(s.contains("role1")){
return Arrays.asList((Permission) new MyPermission("+user+add+1"));
return null;
步骤2:在 shiro.ini 中配置我们的 RolePermissionResolver
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
rolePermissionResolver=com.liwei.role.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver
permissionResolver=com.liwei.permission.MyPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer
securityManager.realms=$myStaticRealm
步骤3:在自定义的 Realm 的授权方法中添加角色
public class MyStaticRealm extends AuthorizingRealm {
* 用于授权
* principalCollection
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("static Realm 中授权的方法");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole("role1");
* 用于认证
* AuthenticationException
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
步骤 4 :判断用户是否具有授权方法中指定角色的权限
代码片段:
currentSubject.checkPermission("+user+add+1")
(终于写完了,不知道能不能讲清楚这件事情,大家光看也是很难理解的,须要自己动手练习,多打出一些帮助理解的代码信息就可以很快理解了)。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:183637次
积分:3871
积分:3871
排名:第6443名
原创:214篇
转载:40篇
评论:57条
我的 GitHub 地址:/weimingge14/
我的码云地址:http://git.oschina.net/weimingge
我的新浪微博:/u/
(4)(2)(20)(1)(30)(2)(13)(5)(2)(9)(8)(9)(4)(6)(4)(33)(26)(14)(2)(3)(53)(1)
最近写的文章主要在 GitHub 的博客上。后续会把质量比较高的内容转移过来。如果有的朋友想先预览一下,可以直接访问 http://www.liwei.party/。我的shiro之旅: 六 自定义shiro的sessionId
shiro有自己的sesison概念,shiro的session并不是java ee的session。通常,我们看到shiro的sessionId格式类似c6395bbc-425d-43b3-a444-04fee5a92e95,是因为shiro产生sesisonId是通过UUID生成的。我们可以看到shiro-core-xx.jar的org.apache.shiro.session.mgt.eis包下有个JavaUuidSessionIdGenerator,shiro的sessionId默认是通过该类生成的。可以看看源码。
public class JavaUuidSessionIdGenerator implements SessionIdGenerator {
* Ignores the method argument and simply returns
* {@code UUID}.{@link java.util.UUID#randomUUID() randomUUID()}.{@code toString()}.
* @param session the {@link Session} instance to which the ID will be applied.
* @return the String value of the JDK's next {@link UUID#randomUUID() randomUUID()}.
public Serializable generateId(Session session) {
return UUID.randomUUID().toString();
是通过调用java的UUID来生成一个唯一的ID。
我们可以自定义类,重写generateId方法,然后把它注入到shiro中。我们可以拿java ee的sessionId作为shiro的sessionId返回。不过我们可以看到generateId方法的参数是Session,这个Session是shiro自定义的,通过它无法拿到java ee的sessionId。我的做法是,写一个拦截器,当讲求过来时,拿到sessionId放到当前线程里,需要的时候从当前线程里拿。类也很简单,代码如下:
* @author Dylan
public final class HttpSessionIdHolder {
private HttpSessionIdHolder(){}
private final static ThreadLocal&String& SESSIONID = new ThreadLocal&String&();
public static String getSessionId(){
return SESSIONID.get();
* @param request
public static void setSessionId(String SessionId){
SESSIONID.set(SessionId);
public static void removeSessionId(){
SESSIONID.remove();
}我们在拦截器里从request拿到sessionId,然后调用setSessionId方法把sessionId保存到当前线程中,需要的时候调用getSessionId就可以得到。
当然,也可以用其他方法。
那么,怎么注入给shiro替换默认的sessionId产生方式呢。在securityManager有个sessionManager属性,在sessionManager有个sessionDAO属性,在sessionDAO有个sessionIdGenerator只要替换就行。如
&bean id=&securityManager& class=&org.apache.shiro.web.mgt.DefaultWebSecurityManager&&
&property name=&sessionManager& ref=&sessionManager&/&
&bean id=&sessionDAO& class=&com.neting.security.infrastructure.shiro.cache.CustomShiroSessionDao&&
&property name=&sessionIdGenerator& ref=&sessionIdGenerator&/&
&bean id=&sessionIdGenerator& class=&com.neting.security.infrastructure.shiro.ShiroSessionIdGenerator&/&
&bean id=&sessionManager& class=&org.apache.shiro.web.session.mgt.DefaultWebSessionManager&&
&property name=&sessionDAO& ref=&sessionDAO&/&
更简单的方式,在这篇文章有介绍。
有必要么?
yijijuechen9999
博主,您好,HttpSessionIdHolder
这个不需要配置吗?
[reply]yijijuechen9999[/reply]不需要配置,有个更好的方法你可以参考一下这篇文章。http://blog.csdn.net/lhacker/article/details/
YIJIJUECHEN_1111
大侠,com.weasel.core这个包整个都没有,能单独传一下么?我也知道,您最近挺忙的,其实您已经供献了好多,我表示深深的感谢!
本分类共有文章17篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";经检测你所在的网络可能存在爬虫,因资源限制,我们只能拒绝你的请求。
如果你是推酷的用户,可以以继续访问使用。
如有疑问,可将IP信息发送到
请求解封。在web.xml中加入
&!-- 过期时间配置 --&
&session-config&&session-timeout&3&/session-timeout&&/session-config&&
&!-- Shiro配置 --&
&filter-name&shiroFilter&/filter-name&
&filter-class&org.springframework.web.filter.DelegatingFilterProxy&/filter-class&
&init-param&
&param-name&targetFilterLifecycle&/param-name&
&param-value&true&/param-value&
&/init-param&
&filter-mapping&
&filter-name&shiroFilter&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
在项目 pom.xml中引入需要的依赖包
&!-- Spring 整合Shiro需要的依赖 --&
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-core&/artifactId&
&version&1.2.1&/version&
&/dependency&
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-web&/artifactId&
&version&1.2.1&/version&
&/dependency&
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-ehcache&/artifactId&
&version&1.2.1&/version&
&/dependency&
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-spring&/artifactId&
&version&1.2.1&/version&
&/dependency&
新建文件&shiro-spring.xml
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd"&
&description&Shiro 配置&/description&
&bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"&
&property name="securityManager" ref="securityManager" /&
&property name="loginUrl" value="/login.jsp" /&
&property name="successUrl" value="/login.jsp" /&
&property name="unauthorizedUrl" value="/error/noperms.jsp" /&
&property name="filterChainDefinitions"&
/login.jsp* = anon
/login.do* = anon
/index.jsp*= anon
/error/noperms.jsp*= anon
/*.jsp* = authc
/*.do* = authc
&/property&
&bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"&
&!--设置自定义realm --&
&property name="realm" ref="monitorRealm" /& --&
&bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /&
&!--自定义Realm 继承自AuthorizingRealm --&
&bean id="monitorRealm" class="com.shiro.service.MonitorRealm"&&/bean& --&
&!-- securityManager --&
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"&
&property name="staticMethod"
value="org.apache.shiro.SecurityUtils.setSecurityManager" /&
&property name="arguments" ref="securityManager" /&
&!-- Enable Shiro Annotations for Spring-configured beans. Only run after --&
&!-- the lifecycleBeanProcessor has run: --&
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" /&
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"&
&property name="securityManager" ref="securityManager" /&
&获取保存的session 信息
Subject subject = SecurityUtils.getSubject();
Object staffInfo = subject.getSession().getAttribute("user");
完整项目下载地址:
阅读(...) 评论()

我要回帖

更多关于 shiro 自定义地址拦截 的文章

 

随机推荐