Shiro(3)——授权
2017-10-14 11:51
176 查看
授权,也就是访问控制,即在应用中控制谁能访问哪些资源,比如页面访问、数据编辑等等操作的权限。在授权操作中需要这样几个关键对象:主体(Subject)、资源(Resources)、权限(Permission)、角色(Role)。
确切地说,shiro支持两种角色模式:
传统角色:一个角色代表着一系列的操作,当需要对某一操作进行授权验证时,只需要判断是否是指定角色即可。这种角色权限简单、模糊,不利于扩展。
权限角色:一个角色拥有一个权限的集合,授权验证时判断该角色是否拥有该权限即可。这种角色模式能够对角色进行详尽的权限描述,适合复杂的权限设计。
Subject实例的方法:
上述属于传统角色模式。Shiro支持断言式的授权验证,当验证成功时并不返回任何值,程序正常执行,失败则抛出异常。Subject的断言验证的方法:
1.2.1基于权限对象的实现
创建org.apache.shiro.authz.Permisson的实例,它是一个接口,并将该实例对象作为参数传递给Subject对象的isPerimitted()方法,如下:
Subject相关方法如下:
1.2.2 基于字符串的实现方式
1.2.3 基于权限对象的断言实现
权限对象也支持断言实现,这里不做赘述。以下是断言实现的相关方法:
相关注解:
2.1
用于注解在用户类/属性/方法上,用以表明当前用户是需要经过认证的用户。
2.2
表明当前用户需为“guest”用户。
2.3
该方法需要用户拥有指定的权限
2.4
在需要权限验证的方法上标注注解:
3.标签式:
在jsp页面内嵌入shiro标签以实现页面级别的权限控制。
首先引入shiro的相关标签库
未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。
在应用程序中调用Subject实例的授权验证方法,例如isPermitted()或者hasRoles()等等,subject将会委托给SubjectManager,再由SubjectManager委托给Authorizer;
Authorizer是真正的授权者,如果我们调用isPermitted(“user:view”),它首先会通过PermissionResolver将字符串转化为相应的Permission实例;
在进行授权之前,会调用相应Realm获取Subject相应的角色/权限来匹配传入的角色/权限;
Authorizer会判断Realm的角色/权限与传入的是否匹配,如果有多个Realm,则会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRoles会返回true,否则返回false,表示授权失败;
如果实现了该接口,则调用isPermitted*/hasRoles*相应方法进行匹配;
如果有一个Realm返回true则授权成功,返回true,否则返回false。
1. 如果调用hasRole*,则直接获取AuthorizationInfo.getRoles()与传入的角色进行比较即可/如果调用的是isPermitted(“user:view”)*,首先通过PermissionResolver将字符串转换成相应的Permission实例,默认使用WildCardPermissionResolver,即转换为通配符的WildCardPermission。
2. 通过AuthorizationInfo.getObjectPermissions()得到permission的集合
主体
主体也就是当前的用户,在Shiro中使用Subject代表当前用户。该用户只有被授权之后才能访问相应的资源资源
应用中的图片、打印、页面、一些业务方法等等一切可以被访问的东西都可以称为资源。资源只能被具备权限的用户所访问。权限
安全策略中的原子单位,通过权限决定用户能否访问应用中的某些资源。Shiro支持粒度权限,所谓粒度,就是指权限的范围大小,例如粗粒度:用户的所有权限,细粒度:访问某一个单个资源的权限。角色
代表了权限的集合,一般赋予用户角色而不是权限,这样在授予权限的时候,我们可以向用户一次性授予一组权限,方便实际开发。例如:技术总监、产品经理、客户经理等等角色可以拥有不同组别的权限。确切地说,shiro支持两种角色模式:
传统角色:一个角色代表着一系列的操作,当需要对某一操作进行授权验证时,只需要判断是否是指定角色即可。这种角色权限简单、模糊,不利于扩展。
权限角色:一个角色拥有一个权限的集合,授权验证时判断该角色是否拥有该权限即可。这种角色模式能够对角色进行详尽的权限描述,适合复杂的权限设计。
授权方式
Shiro有三种形式的授权方式。1.编程式:
1.1 传统角色授权实现
Subject currUser=SubjectUtils.getSubject(); if(currUser.hasRole("admin")){ //拥有该权限 }else{ //验证失败,没有权限 }
Subject实例的方法:
//当用户具有指定角色时返回true boolean hasRole(String roleName); //判定用户是否具有指定列表中角色,按照顺序返回boolean数组 boolean[] hasRoles(List<String> roleNames); //用户具有指定所有角色时返回true boolean hasAllRoles(Collection<String> roleNames);
上述属于传统角色模式。Shiro支持断言式的授权验证,当验证成功时并不返回任何值,程序正常执行,失败则抛出异常。Subject的断言验证的方法:
void checkRole(String var1) throws AuthorizationException; void checkRoles(Collection<String> var1) throws AuthorizationException; void checkRoles(String... var1) throws AuthorizationException;
1.2 基于权限角色授权实现
相比传统授权模式,权限角色的方式耦合性会更低,它不会因为角色的变更而需要对源码进行修改,因此,权限角色模式是更好的访问控制方式。它的编程实现有下列方式:1.2.1基于权限对象的实现
创建org.apache.shiro.authz.Permisson的实例,它是一个接口,并将该实例对象作为参数传递给Subject对象的isPerimitted()方法,如下:
Permission myPermission=new MyPermission(); Subject currUser=SubjectUtils.getSubject(); if(currUser.isPermitted(myPermission)){ //do something }else{ //don't show API for currUser }
Subject相关方法如下:
boolean isPermitted(Permission var1); boolean[] isPermitted(List<Permission> var1); boolean isPermittedAll(Collection<Permission> var1);
1.2.2 基于字符串的实现方式
Permission myPermission=new MyPermission(); Subject currUser=SubjectUtils.getSubject(); if(currUser.isPermitted("endSupport:admin:adminID")){ //do something }else{ //don't show API for currUser } //这里":"分隔的权限表达式是org.apache.shiro.authz.permission.WildcardPermission默认支持的实现方式。这里分别了资源、操作、资源ID。
1.2.3 基于权限对象的断言实现
权限对象也支持断言实现,这里不做赘述。以下是断言实现的相关方法:
checkPermission(Permission perm); checkPermission(String perm); //是否拥有指定所有权限 checkPermissions(Collection<Permission> perms); //同上 checkPermissions(String perms);
2.注解式:
Shiro注解支持AspectJ、Spring、Google-Guice等,可根据应用进行不同的配置。相关注解:
2.1 @RequiresAuthentication
用于注解在用户类/属性/方法上,用以表明当前用户是需要经过认证的用户。@RequiresAuthentication public void updateAccount(Account userAccount) { //this method will only be invoked by a //Subject that is guaranteed authenticated ... }
2.2 @RequiresGuest
表明当前用户需为“guest”用户。2.3 @RequiresPermissions
该方法需要用户拥有指定的权限@RequiresPermissions("resource:operation") public void doSomething(){ //the method is only invioked by a Subject instance which is permitted to do something }
2.4 @RequiresRoles
在需要权限验证的方法上标注注解:@RequiresRoles("admin") public void dealWith(){ // doSomething }
2.5 @RequiresUser
需要当前用户为认证用户,或者已记住用户3.标签式:
在jsp页面内嵌入shiro标签以实现页面级别的权限控制。
首先引入shiro的相关标签库
<%@ taglib prefix="shiro" uri="shiro.apache.org/tags" %>
3.1 guest
验证当前用户是否为访客,即未认证用户(包含未记住)。<shiro:guest> 这里的内容只有“guest”可见。 </shiro:guest>
3.2 user
验证当前用户是否为已认证或已记住的用户。<shiro:user> 这里的内容只有“user”可见。 </shiro:user>
3.3 authenticated和notAuthenticated
验证当前用户是否是已认证用户,不包括已记住用户,这是和user的区别。<shiro:authenticated> 这里的内容只有“authenticated”可见。 </shiro:authenticated>
未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。
<shiro:notAuthenticated> 这里的内容只有“authenticated”可见。 </shiro:notAuthenticated>
3.4 principal
<shiro:principal/>显示当前用户信息,通常是账户登录信息。
3.5 hasRole
验证当前用户是否属于指定角色<shiro:hasRole name="admin"> <!--有权限,doSomething--> <shiro:hasRole>
3.6 lacksRole
它的逻辑和hadRole相反,当用户不属于指定角色时生效<shiro:lacksRole name="admin"> <!--有权限,doSomething--> <shiro:lacksRole>
3.7 hasAnyRole
当用户属于指定多个角色中的任何一个角色时生效<shiro:hasAnyRole name="aaa,bbb,ccc"> <!--有权限,doSomething--> </shiro:hasAnyRole>
3.8 hasPermission
验证当前用户是否拥有指定权限<shiro:hasPermission name="aaa:bbb"> <!--有权限,doSomething--> </shiro:hasPermission >
3.9 lacksPermission
逻辑与hasPermission相反<shiro:lacksPermission name="aaa:bbb"> <!--有权限,doSomething--> </shiro:lacksPermission >
授权流程
在应用程序中调用Subject实例的授权验证方法,例如isPermitted()或者hasRoles()等等,subject将会委托给SubjectManager,再由SubjectManager委托给Authorizer;
Authorizer是真正的授权者,如果我们调用isPermitted(“user:view”),它首先会通过PermissionResolver将字符串转化为相应的Permission实例;
在进行授权之前,会调用相应Realm获取Subject相应的角色/权限来匹配传入的角色/权限;
Authorizer会判断Realm的角色/权限与传入的是否匹配,如果有多个Realm,则会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRoles会返回true,否则返回false,表示授权失败;
ModularRealmAuthorizer的授权流程
首先检查相应的Realm是否实现了Authorizer接口;如果实现了该接口,则调用isPermitted*/hasRoles*相应方法进行匹配;
如果有一个Realm返回true则授权成功,返回true,否则返回false。
Realm授权流程
如果是Realm进行授权的话,应该要继承AuthorizingRealm,流程如下:1. 如果调用hasRole*,则直接获取AuthorizationInfo.getRoles()与传入的角色进行比较即可/如果调用的是isPermitted(“user:view”)*,首先通过PermissionResolver将字符串转换成相应的Permission实例,默认使用WildCardPermissionResolver,即转换为通配符的WildCardPermission。
2. 通过AuthorizationInfo.getObjectPermissions()得到permission的集合
Authorizer、PermissionResolver以及RolePermissionResolver
Authorizer的职责是进行授权(访问控制),是Shiro授权核心的入口点,提供了相应的角色/权限判断接口。相关文章推荐
- 权限框架 - shiro 授权demo
- 18.03.11,web学习第七十一天,bos第十一天,Shiro 授权
- shiro框架(三)- 授权
- Shiro系列之Shiro+Mysql实现用户授权(Authorization)
- 在SpringMVC中开启Shiro注解授权的正确方法
- apache shiro与spring整合、动态filterChainDefinitions、以及认证、授权
- Shiro入门—授权
- Shiro入门2:权限管理入门,用户认证、授权
- Shiro整合SSH开发4:Realm授权,perms过滤器测试和使用方法讲述
- Apache Shiro 标签模式授权
- Shiro授权的三种方式
- Apache Shiro 使用手册(三)Shiro 授权
- shiro之授权
- Shiro的注解(@RequiresRoles,@RequiresPermissions)授权不起作用
- Apache Shiro 是一个框架,可用于身份验证和授权
- 基于AOP实现权限管理:通过shiro认证身份和模拟授权认证
- Shiro实现(一): SSM整合笔记实现登录,授权功能
- shiro用户授权的时候,在springmvc.xml配置出现The prefix "aop" for element "aop:config" is not bound.
- 详解登录认证及授权--Shiro系列
- Apache Shiro 使用手册(三)Shiro 授权