授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限。 
如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等。 

一、授权的三要素 

授权有着三个核心元素:权限、角色和用户。 

权限 
权限是Apache Shiro安全机制最核心的元素。它在应用程序中明确声明了被允许的行为和表现。一个格式良好的权限声明可以清晰表达出用户对该资源拥有的权限。 
大多数的资源会支持典型的CRUD操作(create、read、update、delete),但是任何操作建立在特定的资源上才是有意义的。因此,权限声明的根本思想就是建立在资源以及操作上。 
而我们通过权限声明仅仅能了解这个权限可以在应用程序中做些什么,而不能确定谁拥有此权限。 
于是,我们就需要在应用程序中对用户和权限建立关联。 
通常的做法就是将权限分配给某个角色,然后将这个角色关联一个或多个用户。 

权限声明及粒度 
Shiro权限声明通常是使用以冒号分隔的表达式。就像前文所讲,一个权限表达式可以清晰的指定资源类型,允许的操作,可访问的数据。同时,Shiro权限表达式支持简单的通配符,可以更加灵活的进行权限设置。 
下面以实例来说明权限表达式。 
可查询用户数据 
User:view 
可查询或编辑用户数据 
User:view,edit 
可对用户数据进行所有操作 
User:* 或 user 
可编辑id为123的用户数据 
User:edit:123 

角色 
Shiro支持两种角色模式: 
1、传统角色:一个角色代表着一系列的操作,当需要对某一操作进行授权验证时,只需判断是否是该角色即可。这种角色权限相对简单、模糊,不利于扩展。 
2、权限角色:一个角色拥有一个权限的集合。授权验证时,需要判断当前角色是否拥有该权限。这种角色权限可以对该角色进行详细的权限描述,适合更复杂的权限设计。 
下面将详细描述对两种角色模式的授权实现。 

二、授权实现 

Shiro支持三种方式实现授权过程: 

  • 编码实现
  • 注解实现
  • JSP Taglig实现

1、基于编码的授权实现 

1.1基于传统角色授权实现 
当需要验证用户是否拥有某个角色时,可以调用Subject 实例的hasRole*方法验证。 

  1. Subject currentUser = SecurityUtils.getSubject();
  2. if (currentUser.hasRole("administrator")) {
  3. //show the admin button
  4. } else {
  5. //don't show the button?  Grey it out?
  6. }

相关验证方法如下: 

Subject方法 描述
hasRole(String roleName) 当用户拥有指定角色时,返回true
hasRoles(List<String> roleNames) 按照列表顺序返回相应的一个boolean值数组
hasAllRoles(Collection<String> roleNames) 如果用户拥有所有指定角色时,返回true

断言支持 
Shiro还支持以断言的方式进行授权验证。断言成功,不返回任何值,程序继续执行;断言失败时,将抛出异常信息。使用断言,可以使我们的代码更加简洁。 

  1. Subject currentUser = SecurityUtils.getSubject();
  2. //guarantee that the current user is a bank teller and
  3. //therefore allowed to open the account:
  4. currentUser.checkRole("bankTeller");
  5. openBankAccount();

断言的相关方法: 

Subject方法 描述
checkRole(String roleName) 断言用户是否拥有指定角色
checkRoles(Collection<String> roleNames) 断言用户是否拥有所有指定角色
checkRoles(String... roleNames) 对上一方法的方法重载

1.2 基于权限角色授权实现 
相比传统角色模式,基于权限的角色模式耦合性要更低些,它不会因角色的改变而对源代码进行修改,因此,基于权限的角色模式是更好的访问控制方式。 
它的代码实现有以下几种实现方式: 
1、基于权限对象的实现 
创建org.apache.shiro.authz.Permission的实例,将该实例对象作为参数传递给Subject.isPermitted()进行验证。 

  1. Permission printPermission = new PrinterPermission("laserjet4400n", "print");
  2. Subject currentUser = SecurityUtils.getSubject();
  3. if (currentUser.isPermitted(printPermission)) {
  4. //show the Print button
  5. } else {
  6. //don't show the button?  Grey it out?
  7. }
  8. Permission printPermission = new PrinterPermission("laserjet4400n", "print");
  9. Subject currentUser = SecurityUtils.getSubject();
  10. if (currentUser.isPermitted(printPermission)) {
  11. //show the Print button
  12. } else {
  13. //don't show the button?  Grey it out?
  14. }

相关方法如下: 

Subject方法 描述
isPermitted(Permission p) Subject拥有制定权限时,返回treu
isPermitted(List<Permission> perms) 返回对应权限的boolean数组
isPermittedAll(Collection<Permission> perms) Subject拥有所有制定权限时,返回true

2、 基于字符串的实现 
相比笨重的基于对象的实现方式,基于字符串的实现便显得更加简洁。 

  1. Subject currentUser = SecurityUtils.getSubject();
  2. if (currentUser.isPermitted("printer:print:laserjet4400n")) {
  3. //show the Print button
  4. } else {
  5. //don't show the button?  Grey it out?
  6. }

使用冒号分隔的权限表达式是org.apache.shiro.authz.permission.WildcardPermission 默认支持的实现方式。 
这里分别代表了 资源类型:操作:资源ID 

类似基于对象的实现相关方法,基于字符串的实现相关方法: 
isPermitted(String perm)、isPermitted(String... perms)、isPermittedAll(String... perms) 

基于权限对象的断言实现 

  1. Subject currentUser = SecurityUtils.getSubject();
  2. //guarantee that the current user is permitted
  3. //to open a bank account:
  4. Permission p = new AccountPermission("open");
  5. currentUser.checkPermission(p);
  6. openBankAccount();

基于字符串的断言实现 

  1. Subject currentUser = SecurityUtils.getSubject();
  2. //guarantee that the current user is permitted
  3. //to open a bank account:
  4. currentUser.checkPermission("account:open");
  5. openBankAccount();

断言实现的相关方法 

Subject方法 说明
checkPermission(Permission p) 断言用户是否拥有制定权限
checkPermission(String perm) 断言用户是否拥有制定权限
checkPermissions(Collection<Permission> perms) 断言用户是否拥有所有指定权限
checkPermissions(String... perms) 断言用户是否拥有所有指定权限

2、基于注解的授权实现 
Shiro注解支持AspectJ、Spring、Google-Guice等,可根据应用进行不同的配置。 

相关的注解: 
@ RequiresAuthentication 
可以用户类/属性/方法,用于表明当前用户需是经过认证的用户。 

  1. @RequiresAuthentication
  2. public void updateAccount(Account userAccount) {
  3. //this method will only be invoked by a
  4. //Subject that is guaranteed authenticated
  5. ...
  6. }

@ RequiresGuest 
表明该用户需为”guest”用户 

@ RequiresPermissions 
当前用户需拥有制定权限 

  1. @RequiresPermissions("account:create")
  2. public void createAccount(Account account) {
  3. //this method will only be invoked by a Subject
  4. //that is permitted to create an account
  5. ...
  6. }

@RequiresRoles 
当前用户需拥有制定角色 

@ RequiresUser 
当前用户需为已认证用户或已记住用户 

3、基于JSP  TAG的授权实现 
Shiro提供了一套JSP标签库来实现页面级的授权控制。 
在使用Shiro标签库前,首先需要在JSP引入shiro标签: 

  1. <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

下面一一介绍Shiro的标签: 
guest标签 
验证当前用户是否为“访客”,即未认证(包含未记住)的用户 

  1. <shiro:guest>
  2. Hi there!  Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
  3. </shiro:guest>

user标签 
认证通过或已记住的用户 

  1. <shiro:user>
  2. Welcome back John!  Not John? Click <a href="login.jsp">here<a> to login.
  3. </shiro:user>

authenticated标签 
已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。 

  1. <shiro:authenticated>
  2. <a href="updateAccount.jsp">Update your contact information</a>.
  3. </shiro:authenticated>

notAuthenticated标签 
未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。 

  1. <shiro:notAuthenticated>
  2. Please <a href="login.jsp">login</a> in order to update your credit card information.
  3. </shiro:notAuthenticated>

principal 标签 
输出当前用户信息,通常为登录帐号信息 

  1. Hello, <shiro:principal/>, how are you today?

hasRole标签 
验证当前用户是否属于该角色 

  1. <shiro:hasRole name="administrator">
  2. <a href="admin.jsp">Administer the system</a>
  3. </shiro:hasRole>

lacksRole标签 
与hasRole标签逻辑相反,当用户不属于该角色时验证通过 

  1. <shiro:lacksRole name="administrator">
  2. Sorry, you are not allowed to administer the system.
  3. </shiro:lacksRole>

hasAnyRole标签 
验证当前用户是否属于以下任意一个角色。 

  1. <shiro:hasAnyRoles name="developer, project manager, administrator">
  2. You are either a developer, project manager, or administrator.
  3. </shiro:lacksRole>

hasPermission标签 
验证当前用户是否拥有制定权限 

  1. <shiro:hasPermission name="user:create">
  2. <a href="createUser.jsp">Create a new User</a>
  3. </shiro:hasPermission>

lacksPermission标签 
与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过 

  1. <shiro:hasPermission name="user:create">
  2. <a href="createUser.jsp">Create a new User</a>
  3. </shiro:hasPermission>

三、Shiro授权的内部处理机制 
 
1、在应用程序中调用授权验证方法(Subject的isPermitted*或hasRole*等) 
2、Sbuject的实例通常是DelegatingSubject类(或子类)的实例对象,在认证开始时,会委托应用程序设置的securityManager实例调用相应的isPermitted*或hasRole*方法。 
3、接下来SecurityManager会委托内置的Authorizer的实例(默认是ModularRealmAuthorizer 类的实例,类似认证实例,它同样支持一个或多个Realm实例认证)调用相应的授权方法。 
4、每一个Realm将检查是否实现了相同的 Authorizer 接口。然后,将调用Reaml自己的相应的授权验证方法。 

当使用多个Realm时,不同于认证策略处理方式,授权处理过程中: 
1、当调用Realm出现异常时,将立即抛出异常,结束授权验证。 
2、只要有一个Realm验证成功,那么将认为授权成功,立即返回,结束认证。


Apache Shiro 使用手册(三)Shiro 授权的更多相关文章

  1. Shiro笔记(三)授权

    Shiro笔记(三)授权 一.授权方式 1.编程式: Subject subject=SecurityUtils.getSubject(); if(subject.hasRole("root ...

  2. shiro基础学习(三)—shiro授权

    一.入门程序 1.授权流程        2.授权的三种方式 (1)编程式: 通过写if/else 授权代码块完成. Subject subject = SecurityUtils.getSubjec ...

  3. Shiro学习笔记 三(认证授权)

    第一种首先基于角色的权限控制 1.由于不断的创建SecurityFactory工程等步骤重复多次,所以应该将这些步骤封装成一个工具类 还是首先看一下目录结构 主要用到文件 首先贴一下工具类的方法 pa ...

  4. Apache Shiro 使用手册(三)Shiro 授权(转发:http://kdboy.iteye.com/blog/1155450)

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等. 一.授权的三要素 授权有着三 ...

  5. (转) Apache Shiro 使用手册(三)Shiro 授权

    解惑之处: 使用冒号分隔的权限表达式是org.apache.shiro.authz.permission.WildcardPermission 默认支持的实现方式. 这里分别代表了 资源类型:操作:资 ...

  6. Apache Shiro 使用手册(一)Shiro架构介绍 - kdboy - ITeye技术网站

    转载 原文地址 http://kdboy.iteye.com/blog/1154644 一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理 ...

  7. Apache Shiro 使用手册(一)Shiro架构介绍

    一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能:  认证 - 用户身份识别,常被称为用户"登录": 授权 - ...

  8. Apache Shiro 使用手册---转载

    原文地址:http://www.360doc.com/content/12/0104/13/834950_177177202.shtml (一)Shiro架构介绍 一.什么是Shiro Apache ...

  9. Apache Shiro 使用手册

    http://kdboy.iteye.com/blog/1154644 (一)Shiro架构介绍 一.什么是Shiro  Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加 ...

随机推荐

  1. /proc/stat文件详解(翻译)

    原文地址:http://www.linuxhowtos.org/System/procstat.htm 各种关于系统内核的活动信息都可以在/proc/stat文件中找到,该文件记录了自系统第一次启动以 ...

  2. Java 概述

    一 Java 程序的种类 1)Java 小应用程序(Java Applet) — 在Web浏览器中运行(内嵌Java虚拟机) —特定标记 <APPLET CODE="HelloWorl ...

  3. Windows Store App 用户库文件夹操作

    上面介绍了与用户库文件有关的操作,包括创建.读写等,下面将介绍与用户库文件夹相关的操作. 与文件操作一样,想要对用户库文件夹进行操作,需要首先获取用户库的相应位置,获取的方法上面已经介绍过了,这里不再 ...

  4. post multipart data boundary问题 使用curl 向jersey post文件

    原以为curl 模拟post file跟post string类似,-d参数一加 ,header一加就完了,这次遇到个问题,却怎么都搞不定. curl模拟post提交 与客户端定的协议是: Heade ...

  5. 基于TF-IDF值的汉语语义消歧算法

    RT,学校课题需要233,没了 话说,窝直接做个链接的集合好了,方便以后查找 特征值提取之 -- TF-IDF值的简单介绍 汉语语义消歧之 -- 句子相似度 汉语语义消歧之 -- 词义消歧简介 c++ ...

  6. MongoDB搭建Replica Set Shard Cluster步骤

    本文记录从头搭建一个MongoDB 副本集分片集群的过程. 我们要创建一个这样子的分布式集群:有两个shard,每个shard都是一个replica set,各有两个副本(实际产品应用中还应加上一个仅 ...

  7. git中ssh配置方法

    前提:必须先安装好Git for windows(即msysGit)和TortoiseGit 一,检查本地是否已存在ssh $ cd ~/.ssh $ ls 如果存在id_rsa.pub或者id_ds ...

  8. CSS控制XML与通过js解析xml然后通过html显示xml中的数据

    使用CSS控制XML的显示 book.css bookname{ display:block;color:Red} author{ display:block;font-style:italic} p ...

  9. Linux提供两个格式化错误信息的函数

    #include “stdio.h” Void perror(__const char *__s); 其中__s是出现错误的地方,函数向标准错误输出设备输出如下:s:错误的详细信息. Eg.perro ...

  10. 6、httpd服务的安装、配置

    .本地yum源安装httpd服务 (必须是已搭建好本地yum源) yum install httpd -y (安装httpd) 2.systemctl restart httpd.service   ...