[Apache Shiro]Shiro授权之拥抱主体。

RBAC中的问题

在权限设计中,大部分的系统的权限设计都是使用基于角色的权限控制(Role-Based Access Control)。之所以被如此广泛的接受,推崇。无谓是其结构清晰,容易理解。在正常情况下,100%胜任没有任何问题。但是如果涉及到需要给单个用户单独增加权限时我们只有两种办法来处理,如果你不懂什么叫RBAC请先自行查询.

  1. 给用户增加有该权限的角色
  2. 添加一个新的角色只包含该权限,然后给该用户增加该角色

第一种办法,可能会给该用户赋予其他的权限.所以100%安全的方法只有第二种.当有大量的这种需求时,我们就需要添加大量角色.最糟糕的情况下,角色和权限将会变成一对一关系.相对来说增加权限还好处理一点,假如需求是删除某个用户的某一权限.处理起来就更复杂了.

Shiro授权中的概念

主体(Subject)

文档中对于主体的解释是:
“我们使用单词Subject而不是用户,因为用户通常暗示一个人,而在Shiro中,Subject可以是与您的应用程序交互的任何东西 - 无论是人还是服务(We use word Subject instead of user because user usually implies a human being and in Shiro a Subject can be anything interacting with your application– whether it be a human or a service.)”
说白点Subject只是用户或者一些访问你服务的一些东西而已.也就是权限的最终拥有者.

我认为的主体

说实话这是我一开始没看到主体的文档,理解错误的,不过我这个跟他们无关.只不过也叫主体而已…下面的ER图里t_subject表里也是我这个主体.
文档中并没有主体这一栏,什么是主体?主体是权限的拥有者。
可以是一个用户,一个角色,一个部门,一个小组等(我就想到这几个)。他们都可以拥有自己的权限,主体跟他们是一对一关系,和权限是一对多关系(逻辑关系,实际数据库表结构是多对多关系).当用户授权时,他将得到的是他的角色,部门,小组还有他个人权限的集合。通过主体的概念我们可以将授权细粒度到单个用户。从而解决普通RBAC中单独授权的问题.

权限(Permission)

文档中,第一句话“权限是安全策略的最原子级别”,也就是说资源控制的最细粒度就是权限。权限跟资源的是一对多关系(逻辑关系,资源没有数据库表),跟主体是多对一关系(逻辑关系,实际数据库表结构是多对多关系)。
Shiro中权限以字符串表示。
以“:”分隔表示层级,多个同级权限以“,”分隔.
比如sys:user:read,create就代表了系统用户的读取和创建权限。
以“”表示全部.
sys:user:*表示系统用户的所有权限,通配符“*”也可以省略,写为
sys:user
详见文档

资源(Resource)

文档也没有资源这一栏,资源是什么?资源就是一个可以通过权限控制,达到不同的人得到不同的东西。资源可以是一个url,一个按钮,一行数据,一个字段等等。他们和权限之间是多对一的关系。

根据上述几个概念他们之间的结构应该是
ER图
主体表(t_subject),通过type区分具体关联的表.

Shiro验权之显式和隐式

资源的隐式配置

在有些项目里菜单是保存在数据库的,这里就有这样的问题,假如新增一个菜单,就需要开发者去系统里配置菜单.毕竟菜单的url,样式,需要的权限是开发者自己才知道.不能每次更改都要让开发者在生产环境重新配置.正常来说开发者应该根本不需要登录生产环境.

资源的显式配置

解决隐式配置的方法就是,把所有需要通过权限的资源都写出来,并且通过验权判断是否显示.
JSP的话可以直接通过Shiro的标签库进行验权

		<%@ taglib prefix="shiro" uri=http://shiro.apache.org/tags %>
		<html>
		<body>
		    <shiro:hasPermission name="users:manage">
		        <a href="manageUsers.jsp">
		            Click here to manage users
		        </a>
		    </shiro:hasPermission>
		    <shiro:lacksPermission name="users:manage">
		        No user management for you!
		    </shiro:lacksPermission>
		</body>
		</html>

类里的注解验权

		//Will throw an AuthorizationException if none
		//of the caller’s roles imply the Account
		//'create' permission
		@RequiresPermissions("account:create")public void openAccount( Account acct ) {
		   //create the account
		}

等其他验权方式.

隐式的权限验证

		//get the current Subject 
		Subject currentUser = SecurityUtils.getSubject();
		
		if (currentUser.hasRole("administrator")) {
		    //show a special button‏
		} else {
		    //don’t show the button?)‏
		}

看这段代码我们能发现什么问题?乍看起来好像没问题,就好像重写对于多态.但是如果programmer角色也需要显示这个button呢?我们只能改为

		//get the current Subject 
		Subject currentUser = SecurityUtils.getSubject();
		
		if (currentUser.hasRole("administrator")||currentUser.hasRole("programmer")) {
		    //show a special button‏
		} else {
		    //don’t show the button?)‏
		}

这一点改动意味着项目要重新编译上线.这也太不灵活了.盖个权限都要重新上线.在隐式验权里我们并没有用安全策略的原子级别—Permission来校验,而是用了一个Role,它并不是原子级别,它可以含有多Permission.
所以这种非原子性验权,不提倡大家使用.

显式的权限验证

		String perm = "printer:print:laserjet4400n";
		
		if(currentUser.isPermitted(perm)){
		    //show the print button?
		} else {
		    //don’t show the button?
		}

显式验权也就是直接校验权限了.

结语

Shiro框架不单单是给我们简化了权限系统的开发,同时它在理念上给我们指引了方向.我见过很多的系统里并没有正确的使用到它,感觉非常惋惜,随做此文.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值