授权或叫访问控制是对资源指定访问权限的功能。简单而言就是谁能够访问什么。在授权领域有三个关键元素——permissions, roles, and users——在shiro中我们经常会引用。
Permissions(权限)是安全策略中最原子级别的概念,并且他们够不语句表达。权限代表在我们的系统中可以做什么。良好的权限形式描述了资源类型以及拥有它的操作者能够对这些资源做什么。比如是否可以下载文档、是否能够看到按钮等等。此处一定要理解到权限仅仅表达了什么样的动作可以执行,而并没有说谁能够做这些动作。
对于数据相关的资源,其基本操作包括创建(create)、读取(read)、更新(update)和删除(delete),其实就是众多系统开发者都熟悉的CRUD。
上面的权限仅仅描述了资源类型的级别,如可以看到按钮的权限描述,并没有描述这个资源的实例是什么,我们可以这样再来描述下:可以看到编辑按钮。其实在shiro中我们可以定义任意深度的权限。下面列列举三种权限级别#
资源级别(Resource level)——这是一种很宽广和容易构建的权限,就像上面的例子一样。
资源实例级别(instance level)——这种权限指定了权限的实例(具体资源——根据定义的深度不同不同,例如“门”是资源,它的实例可以是厨房门,但这可以再往深处定义我家厨房门)。
属性级别(attribute level)——这里指定了一个具体资源或者资源类型的属性级别的权限。
角色(Roles):在授权范围内,角色是一种有效的用于简化管理权限(permissions)和用户(users)的权限集合。Shiro支持两种角色类型——暗含的角色(Implicit Roles)和明确的角色(explicit
Roles)。
什么是暗含的角色呢?可以简单的理解为在应用中实际上为真正定义或剥离这种角色,而仅仅是混杂在代码中,且往往这种角色直接和资源相关联。例如一个系统中通过判断用户是档案馆管理员员(这就是一种暗含角色)则可以查阅渤海油田档案,其实诸如“档案馆工作人员”等名字(暗含角色)的存和系统中档案查阅功能模块所做的事情没有相关性。这种使用角色的习惯对简单的系统无所谓,但略复杂的系统则会带来许多维护和管理的问题。
什么又是明确的角色呢?它是指被明确指定了权限的角色,即这种角色是一种明确的权限集合。例如一个系统用户之所以能够查阅渤海油田档案是因为它所属的档案馆管理员角色拥有档案查阅权限,而不单单是因为他是管理员,即便他是普通职工,只要具备档案查阅权限,则其即可查阅档案。
Users:在shiro中Users就是subject的实例,不单单指自然人,也可以是软件服务等。一个用户能够执行系统中某些操作是因为它的关联的角
色或者直接拥有的权限。
在了解了授权的基础知识后,我要清楚java环境下如何使用shiro检测已授权限。shiro中可以使用三种方式来授权:直接编码、在java方法上使用注解、在jsp中使用taglib以控制表单的输出。
直接编写代码方式下我们即可来检测用户是否具备有个角色,也可以来检测是否具备某种权限。检测角色使用Subject的hasRole()方法,但这种方式如果后续涉及到角色的增加、删除等操作就不得不找到源码进行修改,不建议使用。示例如下所示。
//get the current Subject
Subject currentUser =
SecurityUtils.getSubject();
if (currentUser.hasRole(“administrator”)) {
//show a special button?
} else {
//don’t show the button?)?
}
在代码中检测权限有两种方式,一种是基于Permission对象的检测,一种是基于字符串的检测方式。这种检测使用的是Subject的isPermitted()方法。示例代码如下所示。
Subject currentUser = SecurityUtils.getSubject();
Permission printPermission =
new PrinterPermission(“laserjet3000n”,“print”);
If (currentUser.isPermitted(printPermission)) {
//do one thing (show the print button?)?
} else {
//don’t show the button?
}
String perm = “printer:print:laserjet4400n”;
if(currentUser.isPermitted(perm)){
//show the print button?
} else {
//don’t show the button?
}
上文中字符串的方式采用的是shiro的WildCardPermissions格式。这种字符串通配符权限表达方式的格式为:” 资源:操作:资源实例"。具体可以参考:http://shiro.apache.org/permissions.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
}
//Throws an AuthorizationException if the caller
//doesn’t have the ‘teller’ role:
@RequiresRoles( “teller” )
public void openAccount( Account acct ) {
//do something in here that only a teller
//should do
}
最后一种是taglib方式。在jsp中引入shiro的tag,之后使用<shiro:hasPermission>来判断是否具备某种权限,使用<shiro:lacksPermission>来判断不具备有种权限时表单的显示。除此外还有许多其他tag可以使用,此处仅以这两种为例如下所示。
<%@ 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>