`
jinnianshilongnian
  • 浏览: 21504003 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418672
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008769
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639487
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259916
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597310
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250216
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858947
Group-logo
跟我学Nginx+Lua开...
浏览量:701999
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785223
社区版块
存档分类
最新评论

简单shiro扩展实现NOT、AND、OR权限验证

 
阅读更多

使用过shiro的朋友应该都知道在要想实现any permission的验证是比较麻烦。

 

很多朋友刚开始接触时以为如<shiro:hasPermission name="showcase:tree:*"> 代表验证拥有任何权限,但这是错误的。如果我们把showcase:tree:*授权给用户,那么此时表示用户具有showcase:tree资源的任意权限,如<shiro:hasPermission name="showcase:tree:*">或shiro:hasPermission name="showcase:tree:create">都能验证成功。

 

还有朋友认为<shiro:hasPermission name="showcase:tree:create,update"> 是或的关系,也不是,默认是且的关系。

 

下载了最新的shiro1.3.0-SNAPSHOT 发现并没有增加新的标签或其他支持。

 

因此我们需要简单的扩展下shiro来支持像spring security 3那样的@Secured支持表达式的强大注解。

 

不过有人已经提交了一个基于ANTLR实现的@Secured,可以在其JIRA上找到,在其官网的[ Version 2 Brainstorming ]也介绍并探讨了使用ANTLR语法的@Secured注解,可能在为了shiro 2版本添加进去,估计还得大半年,现在是1.3.0-SNAPSHOT。

 

对于我而言暂时不需要那么复杂的。因此暂时考虑扩展下默认的实现,在不添加任何注解/标签的基础上,简单的支持NOT、AND、OR即可。因此我们扩展AuthorizingRealm,并修改:

 

    private static final String OR_OPERATOR = " or ";
    private static final String AND_OPERATOR = " and ";
    private static final String NOT_OPERATOR = "not ";
    /**
     * 支持or and not 关键词  不支持and or混用
     * @param principals
     * @param permission
     * @return
     */
    public boolean isPermitted(PrincipalCollection principals, String permission) {
        if(permission.contains(OR_OPERATOR)) {
            String[] permissions = permission.split(OR_OPERATOR);
            for(String orPermission : permissions) {
                if(isPermittedWithNotOperator(principals, orPermission)) {
                    return true;
                }
            }
            return false;
        } else if(permission.contains(AND_OPERATOR)) {
            String[] permissions = permission.split(AND_OPERATOR);
            for(String orPermission : permissions) {
                if(!isPermittedWithNotOperator(principals, orPermission)) {
                    return false;
                }
            }
            return true;
        } else {
            return isPermittedWithNotOperator(principals, permission);
        }
    }

    private boolean isPermittedWithNotOperator(PrincipalCollection principals, String permission) {
        if(permission.startsWith(NOT_OPERATOR)) {
            return !super.isPermitted(principals, permission.substring(NOT_OPERATOR.length()));
        } else {
            return super.isPermitted(principals, permission);
        }
    }

 

如上代码即可以实现简单的NOT、AND、OR支持,不过缺点是不支持复杂的如AND、OR组合。

 

这样我就可以像如下使用了,不需要额外的标签,就是太长,如果实现如showcase:tree:(create|update|delete)这种语法相对而言简单多了,希望未来官网支持更好的方式:

<shiro:hasPermission name="showcase:tree:create or showcase:tree:update or showcase:tree:delete">

 

shiro总起来说使用起来还是比较舒服的,就是更新太慢。。。。

 

17
9
分享到:
评论
17 楼 java_zhenke 2015-06-17  
今天发现一个小坑,我在页面很多按钮加上shiro.hasPermission来划分权限,忘记在自己的Realm实现对应的spring-shiro.xml中配置缓存:
<bean id="shiroRealm" class="com.dc.web.realm.ShiroRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
<property name="cachingEnabled" value="true" />
        <property name="authenticationCachingEnabled" value="true"/>
        <property name="authenticationCacheName" value="authenticationCache"/>
        <property name="authorizationCachingEnabled" value="true"/>
        <property name="authorizationCacheName" value="authorizationCache"/>
</bean>
结果shiro每次遇到hasPermission都会去自己的ShiroRealm中执行一次doGetAuthorizationInfo,造成每次都得去执行一堆验证和取权限的SQL,页面响应时间都会受到影响。
16 楼 Dead_knight 2013-12-11  
jinnianshilongnian 写道
happylouis 写道
如果用户有权限:添加A---2;删除B---3;修改B---4
那用户的权限值 purview =2^2+2^3+2^4=28,也就是2的权的和了。
化成二进制可以表示为11100
这样,如果要验证用户是否有删除B的权限,就可以通过位与运算来实现。
即是:int value = purview &((int)Math.pow(2,3));
你会发现,当用户有操作权限时,运算出来的结果都会等于这个操作需要的权限值!


原理:
以上面的式子为例:purview & 2^3 也就是 28&8
将它们化成二进制有
  11100
& 01000
-------------------
  01000 == 8(十进制) == 2^3

请教楼主,这个权限算法用shiro要如何实现呢

先要明确一下;shiro默认实现都是进行字符串匹配;你这种的话;需要重写自己的AuthorizingRealm;这里有个很大的问题就是比如shiro支持:user--等价于--user:*,所以这种情况比较棘手,shiro本身默认实现都是基于字符串匹配;所以你要重写整个shiro的相关实现(最主要的就是AuthorizingRealm);然后权限字符串需要是如:资源:权限,其中权限不能省略; 这样的话你首先得到最后一个权限字符串;转换成数字;然后进行运算;如果成功返回true即可;

这种比字符串匹配感觉麻烦多了;不让字符串来的直观;效率也不会差很多。


我个人觉得没必要纠结于权限匹配算法。因为这个权限是自身项目的匹配算法,而shiro自己会帮你匹配的,所以这个算法根本不需要。
我的思路是:
1、自定义资源-权限的映射关系,那么你添加到元数据里面的就是[添加A,2]这样的映射。参考:
http://git.oschina.net/yuqs/snaker-demo/blob/master/src/main/java/org/snaker/framework/security/shiro/ShiroDefinitionSectionMetaSource.java
2、用户登录的时候,加载拥有的权限列表,而你的是权值,则需要换算之后再添加。即你要解决的是把28拆开成:2^2+2^3+2^4,然后每组除以2,再进行添加,即["2","3","4"]参考:
http://git.oschina.net/yuqs/snaker-demo/blob/master/src/main/java/org/snaker/framework/security/shiro/ShiroAuthorizingRealm.java
或者第一步添加的数据是:[添加A,(2,3)]
第二部只要把28拆开成2^2+2^3+2^4,然后每组格式为为(2,2),(2,3),(2,4)这样的

我的只是个思路,感觉都要对28进行拆
15 楼 jinnianshilongnian 2013-12-11  
happylouis 写道
如果用户有权限:添加A---2;删除B---3;修改B---4
那用户的权限值 purview =2^2+2^3+2^4=28,也就是2的权的和了。
化成二进制可以表示为11100
这样,如果要验证用户是否有删除B的权限,就可以通过位与运算来实现。
即是:int value = purview &((int)Math.pow(2,3));
你会发现,当用户有操作权限时,运算出来的结果都会等于这个操作需要的权限值!


原理:
以上面的式子为例:purview & 2^3 也就是 28&8
将它们化成二进制有
  11100
& 01000
-------------------
  01000 == 8(十进制) == 2^3

请教楼主,这个权限算法用shiro要如何实现呢

先要明确一下;shiro默认实现都是进行字符串匹配;你这种的话;需要重写自己的AuthorizingRealm;这里有个很大的问题就是比如shiro支持:user--等价于--user:*,所以这种情况比较棘手,shiro本身默认实现都是基于字符串匹配;所以你要重写整个shiro的相关实现(最主要的就是AuthorizingRealm);然后权限字符串需要是如:资源:权限,其中权限不能省略; 这样的话你首先得到最后一个权限字符串;转换成数字;然后进行运算;如果成功返回true即可;

这种比字符串匹配感觉麻烦多了;不让字符串来的直观;效率也不会差很多。

14 楼 happylouis 2013-12-11  
如果用户有权限:添加A---2;删除B---3;修改B---4
那用户的权限值 purview =2^2+2^3+2^4=28,也就是2的权的和了。
化成二进制可以表示为11100
这样,如果要验证用户是否有删除B的权限,就可以通过位与运算来实现。
即是:int value = purview &((int)Math.pow(2,3));
你会发现,当用户有操作权限时,运算出来的结果都会等于这个操作需要的权限值!


原理:
以上面的式子为例:purview & 2^3 也就是 28&8
将它们化成二进制有
  11100
& 01000
-------------------
  01000 == 8(十进制) == 2^3

请教楼主,这个权限算法用shiro要如何实现呢
13 楼 jinnianshilongnian 2013-05-23  
q474818917 写道
<!-- Shiro's main business-tier object for web-enabled applications -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="sessionMode" value="native"/>
		<property name="realm" ref="shiroDbRealm" /> 
		<property name="cacheManager" ref="shiroEhcacheManager" />
	</bean>
	
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionDAO" ref="sessionDAO"/>
	</bean>
	<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
		<property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
	</bean>

我这样是不是指定了cache name了?可是我还是获取不到,又来寻求您帮助了

这个是activeSessionsCacheName  session的 不是验证的

你需要给realm加  有两个
1、权限的
2、用户的
12 楼 q474818917 2013-05-23  
<!-- Shiro's main business-tier object for web-enabled applications -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="sessionMode" value="native"/>
		<property name="realm" ref="shiroDbRealm" /> 
		<property name="cacheManager" ref="shiroEhcacheManager" />
	</bean>
	
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionDAO" ref="sessionDAO"/>
	</bean>
	<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
		<property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
	</bean>

我这样是不是指定了cache name了?可是我还是获取不到,又来寻求您帮助了
11 楼 jinnianshilongnian 2013-05-22  
q474818917 写道
jinnianshilongnian 写道
q474818917 写道
我想问您个问题:
我动态的修改了用户的角色,怎么才能让该用户获取新的permission
也就是前台has_permission

这是你查询的问题:
一般的方案是:
1、第一个查出来缓存
2、如果修改了权限 则清空缓存 下次重新查

我看了一下,它是用ehcache做缓存的,但是我getAuthorizationCache这个居然没取到Cache
,不知道怎么回事

你需要自己配置上cache name 然后他按照principals去取。

不过不建议你使用这个 建议直接自己弄个切面 进行缓存  这样可以更好的控制缓存的过期等
10 楼 q474818917 2013-05-22  
jinnianshilongnian 写道
q474818917 写道
我想问您个问题:
我动态的修改了用户的角色,怎么才能让该用户获取新的permission
也就是前台has_permission

这是你查询的问题:
一般的方案是:
1、第一个查出来缓存
2、如果修改了权限 则清空缓存 下次重新查

我看了一下,它是用ehcache做缓存的,但是我getAuthorizationCache这个居然没取到Cache
,不知道怎么回事
9 楼 jinnianshilongnian 2013-05-22  
q474818917 写道
我想问您个问题:
我动态的修改了用户的角色,怎么才能让该用户获取新的permission
也就是前台has_permission

这是你查询的问题:
一般的方案是:
1、第一个查出来缓存
2、如果修改了权限 则清空缓存 下次重新查
8 楼 q474818917 2013-05-22  
我想问您个问题:
我动态的修改了用户的角色,怎么才能让该用户获取新的permission
也就是前台has_permission
7 楼 jinnianshilongnian 2013-05-09  
Dead_knight 写道
jinnianshilongnian 写道
semmy 写道
支持来个shiro专题系列

shiro使用起来确实比spring security简单多了 而且支持比较优秀的基于资源的权限验证,这样可维护性要好很多  后续可能介绍shiro 不过时间啊 时间

昨天看到你建议我出个shiro的专题。看到你已经写了两篇shiro的,顶一个。
shiro也研究过的,只是没有新的正式项目实际用到shiro,所以不便误导别人(特别是想正式使用shiro的)。不过现在网上shiro的资料也不少,springside4也把shiro整合进去了,完全可以参考,呵呵

我的这个就是使用中遇到的问题记录下来  shiro缺点就是更新比较慢 比不了spring这个庞然大物
6 楼 Dead_knight 2013-05-09  
jinnianshilongnian 写道
semmy 写道
支持来个shiro专题系列

shiro使用起来确实比spring security简单多了 而且支持比较优秀的基于资源的权限验证,这样可维护性要好很多  后续可能介绍shiro 不过时间啊 时间

昨天看到你建议我出个shiro的专题。看到你已经写了两篇shiro的,顶一个。
shiro也研究过的,只是没有新的正式项目实际用到shiro,所以不便误导别人(特别是想正式使用shiro的)。不过现在网上shiro的资料也不少,springside4也把shiro整合进去了,完全可以参考,呵呵
5 楼 jinnianshilongnian 2013-05-09  
semmy 写道
支持来个shiro专题系列

shiro使用起来确实比spring security简单多了 而且支持比较优秀的基于资源的权限验证,这样可维护性要好很多  后续可能介绍shiro 不过时间啊 时间
4 楼 semmy 2013-05-09  
支持来个shiro专题系列
3 楼 jinnianshilongnian 2013-05-09  
rekoe.net 写道
这个类如何生效?

不过官网jira给出更强大的实现 使用antlr做语法分析 不过需要添加好多东西,如果不需要那么麻烦 还是这样简单点
2 楼 jinnianshilongnian 2013-05-09  
rekoe.net 写道
这个类如何生效?

我们在实现shiro的时候如果不用JdbcRealm, 都要自己实现一个,或者覆盖JdbcRealm,或者实现AuthorizingRealm等,此时覆盖其isPermitted(PrincipalCollection principals, String permission) 即可 
1 楼 rekoe.net 2013-05-09  
这个类如何生效?

相关推荐

    SpringBoot整合Shiro示例实现动态权限加载更新+Session共享+单点登录

    SpringBoot整合Shiro示例实现动态权限加载更新+Session共享+单点登录 SpringBoot整合Shiro示例实现动态权限加载更新+Session共享+单点登录 SpringBoot整合Shiro示例实现动态权限加载更新+Session共享+单点登录 ...

    vue与shiro结合实现权限按钮

    Vue.js作为一个轻量级的前端框架,搭配Apache Shiro这样的安全管理框架,可以有效地实现前端的细粒度权限管理,如按钮级别的权限控制。本文将详细介绍如何在Vue项目中结合Shiro实现这一功能,以及所需的前置技术。 ...

    SpringBoot 集成 Shiro 实现动态uri权限

    SpringBoot集成Shiro实现动态URI权限是一个常见的权限管理实践,主要目的是为了实现更灵活、更安全的用户访问控制。在Web应用中,权限控制通常包括角色管理、菜单管理、操作权限(URI)管理等,而动态URI权限则允许...

    SpringBoot 整合 Shiro,实现从数据库加载权限、权限的动态更新、Session共享

    然后是Apache Shiro,这是一个强大且易于使用的Java安全框架,提供了身份验证(登录)、授权(权限管理)、会话管理和加密等核心功能。Shiro能够直接与应用程序代码集成,使得安全控制更加直观和简单。 1. **从...

    SpringBoot + shiro Demo 简单登录验证权限验证

    这个Demo提供了一个使用SpringBoot和Shiro实现简单登录验证和权限控制的实例,对于学习和理解这两个框架的集成非常有帮助。通过阅读和实践这个Demo,开发者可以更好地掌握如何在实际项目中应用SpringBoot的便捷性和...

    shiro实现授权登陆验证

    4. **权限验证**: - Shiro提供了注解`@RequiresRoles`和`@RequiresPermissions`,可以直接在方法上标记,实现基于注解的权限控制。 - 也可以通过编程式的方式,如`Subject.checkRole()`和`Subject....

    springMVC+shiro实现动态权限验证.zip

    springMVC+shiro实现动态权限验证,实现动态设置用户角色,根据角色来决定哪些url可以访问 抱歉了各位需要修改下配置文件(org.eclipse.wst.common.component) &lt;?xml version="1.0" encoding="UTF-8"?&gt; ...

    基于Shiro 拦截URL,实现权限控制

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证、授权、会话管理和加密等功能,使得在Java应用中处理安全性变得更加简单。在这个主题中,“基于Shiro拦截URL,实现权限控制”意味着我们将探讨如何利用...

    spring boot+shiro 权限认证管理案例

    Spring Boot 和 Apache Shiro 的整合是企业级应用中常见的权限认证和安全管理方案。Spring Boot 提供了简化 Java 应用程序...在实际开发中,还可以根据需求扩展 Shiro 功能,例如集成 JWT 认证、实现动态权限控制等。

    Springboot+Shiro+Redis实现RBAC用户权限管理

    总结来说,"Springboot+Shiro+Redis实现RBAC用户权限管理"是一种高效、可扩展的解决方案,它结合了Springboot的便捷性、Shiro的权限管理功能和Redis的高速缓存能力,通过org.creazycake插件进一步简化了整合过程。...

    Shiro根据用户权限显示不同的菜单.Shiro根据权限显示指定菜单

    在这个场景中,我们关注的是如何利用Shiro实现根据用户权限动态显示不同的菜单。 首先,理解Shiro的核心概念是关键。在Shiro中,权限分为角色(Role)和权限(Permission)。角色是一组权限的集合,权限则具体描述...

    基于shiro前后端分离分布式权限管理(完整后端代码)

    5. 前后端通过RESTful API进行通信,前端向后端请求权限验证,后端通过Shiro处理请求并返回结果。 总之,这个基于Shiro的分布式权限管理系统结合了现代Web开发的最佳实践,利用Shiro的强大功能和Redis集群的高效...

    SpringBoot整合Shiro,实现从数据库加载权限、权限的动态更新、Session共享

    在本项目中,我们将深入探讨如何利用SpringBoot与Shiro结合,实现从数据库加载权限、权限的动态更新以及Session共享。 1. **Shiro简介**: Apache Shiro是一个轻量级的安全框架,它提供了认证、授权、会话管理和...

    shiro权限案例demo

    在这个"shiro权限案例demo"中,我们将深入探讨Shiro如何实现用户权限的管理。 首先,让我们了解Shiro的核心组件: 1. **Subject**:是Shiro的中心概念,代表了当前“安全的用户”。它提供了进行认证、授权、会话...

    SSM+Shiro实现权限角色控制

    SSM+Shiro框架组合是Java Web开发中常见的权限管理和安全控制解决方案,它结合了Spring、Spring MVC和MyBatis三大框架与Apache Shiro的安全库。这个项目利用这些技术实现了一个具备角色和权限控制功能的系统,使得...

    sprinbgboot实现的shiro权限验证源码

    分布式架构实现,基于springboot的shiro权限验证源码,包括redis,activeMq以及邮件通知等,websocket通信,mybatis链接数据库,完整的权限验证架构。

    SSM+Shiro+redis实现的权限系统

    SSM+Shiro+Redis实现的权限系统是一个常见的企业级应用架构,主要用于构建安全、高效且可扩展的Web应用程序。这个系统结合了Spring、SpringMVC、MyBatis三大核心框架,以及Apache Shiro安全框架和Redis缓存技术,以...

    spring+shiro 增删改查权限控制

    不过,对于简单的权限控制需求,Shiro可能更加轻便易用。 在具体实现中,我们通常会在Spring的Service层调用Shiro的API进行权限判断。比如,使用`Subject`对象的`isPermitted()`或`checkPermission()`方法来检查...

    SSM+Shiro+Redis实现项目的权限管理

    在`ShiroTest`这个文件中,可能包含了测试Shiro权限控制的代码,例如设置安全配置、创建安全管理器、定义权限规则、模拟用户登录以及进行权限验证的测试用例。这些测试有助于确保权限管理功能的正确性和稳定性。 ...

Global site tag (gtag.js) - Google Analytics