shiro讲解之Authorization(三)
shiro讲解之 Authorization (三)
在之前的章节中我们学习了Shiro 的授权⽅式和实现。就Shiro 的 授权粒度⽽⾔,我们之前学习都是Shiro 的粗粒度。在授权粒度上 Shiro 做的⾮常好,即我们既可以实现粗粒度的授权(⼀般指 Authorization)和细粒度的鉴权(Permission)。
概念
⼀定程度上⽽⾔ Shiro 的 Permisssion 指的是Shiro 对权限细粒度的划分。在我们之前学习的章节中给我们所接触到的 Authorization都是粗粒度的授权即⼀个实例(⾓⾊)拥有相应资源的所有操作权限。
Shiro Permission 在做授权是规定某些实例在访问某系特定资源(该实例享有的前提下)时能做哪些操作(对资源⽽⾔)。我想这样来解释Shiro Permission 仍然很抽象。下⾯我⽤⼀个案例来说明⼀下 Shiro Persimission 定义的体现:
假如公司有⼀台名为Printer158 的打印机(资源),我们在使⽤ Shiro 做权限设计时采取⼀下做法:
管理员(⾓⾊或者实例)能够对该台打印机做任何操作(⽐如初始化设置、设置、内部数据管理、打印等)。
公司员⼯(⾓⾊或者实例) 只能使⽤打印功能(操作)。
在以上的案例中有三个很关键的词语:资源-操作-实例。较为完整的表达为某个资源可以被做某些操作于某些实例⽽⾔,这样的表达在中⽂中是⾮常拗⼝的但你若了解外国⼈(尤其是欧美⼈)的表达⽅式你就会发现这其实是按照外国⼈的思维逻辑和表达⽅式惯性的体现,这⾥就不赘述了。
资源-操作-实例
资源-操作-实例 是 Shiro 做细粒度鉴权 persmission时的⼀种规则。
含义
对哪个资源的哪个实例可以进⾏什么操作
扩展
默认⽀持通配符权限字符串,: 表⽰资源/操作/实例的分割;, 表⽰操作的分割,* 表⽰任意资源/操作/实例。
单个权限
user:query、user:edit。
冒号是⼀个特殊字符,它⽤来分隔权限字符串的下⼀部件:第⼀部分是权限被操作的领域,第⼆部分是被执⾏的操作。
多个值:每个部件能够保护多个值。因此,除了授予⽤户 user:query和 user:edit 权限外,也可以简单地授予他们⼀个:user:query, edit。
还可以⽤ * 号代替所有的值,如:user:* , 也可以写:*:query,表⽰某个⽤户在所有的领域都有 query 的权限。
例⼦
单个资源多个权限 user:query user:add 多值 user:query,add
单个资源所有权限 user:query,add,update,delete user:*
所有资源某个权限 *:view
实例级访问控制
规则: 资源标识符:操作:对象实例 ID
这种情况通常会使⽤三个部件:域、操作、被付诸实施的实例。如:user:edit:manager
也可以使⽤通配符来定义,如:user:edit:、user::、user::manager
部分省略通配符:缺少的部件意味着⽤户可以访问所有与之匹配的值,⽐如:user:edit 等价于 user:edit :*、
user 等价于 user:* :*
注意:通配符只能从字符串的结尾处省略部件,也就是说 user:edit 并不等价于 user:*:edit
例⼦
单个实例的单个权限 printer:query:lp7200 printer:print:epsoncolor
对资源printer的lp7200实例拥有query权限。
对资源printer的epsoncolor实例拥有query权限。
所有实例的单个权限 printer:print:*
对资源printer的所有r实例拥有query权限。
所有实例的所有权限 printer::
对资源printer的1实例拥有所有权限。然后通过如下代码判断
subject().checkPermissions(“printer:setting:1”, “printer:printe:2”);
单个实例的所有权限 printer:*:lp7200
对资源printer的lp7200实例拥有所有权限
单个实例的多个权限 printer:query,print:lp7200
对资源printer的lp7200实例拥有query,print权限
实例
下⾯我们将通过实例来深了解 Shiro permisssion细粒度鉴权是怎样实现的。
延⽤之前的框架Spring+shiro+Spring MVC
配置filterChainDefinition
<bean id="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager"ref="securityManager" />
<property name="loginUrl" value="/login/toLogin" />
<property name="successUrl" value="/example/index" />
shiro权限控制<property name="unauthorizedUrl" value="/example/unauthorized" />
<property name="filterChainDefinitions">
<value>
/login/toLogin = anon
/login/loginVal = anon
/login/logout = logout
/
example/admin =roles[admin]
/example/admin =perms[admin:view:*]
/example/user = roles[user]
/example/user = perms[user:view:*]
/** = authc
</value>
</property>
</bean>
使⽤多Realm 做 Authorization
ShiroRealm
// 授权会被 shiro 回调的⽅法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("ShiroRealm Authorization");
// 1. 从 PrincipalCollection 中来获取登录⽤户的信息
Object principal = PrimaryPrincipal();
// 2. 利⽤登录的⽤户的信息来⽤户当前⽤户的⾓⾊或权限(可能需要查询数据库)        Set<String> roles = new HashSet<>();
roles.add("admin");
List<String> permissions=new ArrayList<>();
permissions.add("admin:view:*");
/*  if ("admin".equals(principal)) {
roles.add("admin");
}*/
// 3. 创建 SimpleAuthorizationInfo, 并设置其 roles 属性.
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加⾓⾊
info.addRoles(roles);
//添加权限
info.addStringPermissions(permissions);
// 4. 返回 SimpleAuthorizationInfo 对象.
return info;
}
MyRealm
MyRealm
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("MyRealm Authorization");
Object principal = PrimaryPrincipal();
Set<String> roles = new HashSet<>();
roles.add("user");
Set<String> permissions = new HashSet<>();
permissions.add("user:view:*");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
jsp 页⾯校验
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="shiro" uri="/tags"%>
<%
String path = ContextPath();
String basePath = Scheme() + "://" + ServerName() + ":" + ServerPort()
+ path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "/TR/html4/loose.dtd"> <html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hi ~~shiro</h1>
<h4>This Subject has role of User</h4>
<!-- 只有admin ⾓⾊才能显⽰⼀下内容 -->
<shiro:hasRole name="admin">
Only admin can access to those words
</shiro:hasRole>
<br>
<br>
<!-- 只有user ⾓⾊才能显⽰⼀下内容 -->
<shiro:hasRole name="user">
Only User can access to those words
</shiro:hasRole>
<br>
<br>
<shiro:hasRole name="Manager">
Only Manager can access to those words
</shiro:hasRole>
<br>
<br>
<!-- 只有 user:view:* 权限才能显⽰⼀下内容 -->
<shiro:hasPermission name="user:view:*">
Only User has 'user:view:*' can access to those words
</shiro:hasPermission>
<br>
<br>
<!-- 只有 admin:view:* 权限才能显⽰⼀下内容 -->
<shiro:hasPermission name="admin:view:*">
Only Admin has 'admin:view:*' can access to those words
</shiro:hasPermission>
<br>
<br>
<shiro:hasPermission name="manager:view:*">
Only Manager has 'manager:view:*' can access to those words
</shiro:hasPermission>
<br>
<br>
<a href="<%=basePath%>/login/logout">Logout</a>
</body>
</html>
校验结果
Permission 鉴权的⽅式
在之前的学习中我们了解到了 Shiro 的Authorization有三种⽅式,作为 细粒度化的 Authorization,Permission 同样也⽀持粗粒度的Authorization 的三种⽅式即代码判断,注解,JSP页⾯校验。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。