Shiro框架学习记录(一)

Shiro 框架了解

1. 什么是 Apache Shiro?

1.1 Shiro 解决了哪些问题?

Shiro 提供了保护应用的 API - 应用安全的四要素

  • 认证 - 用户身份识别,常被称为用户“登录”
  • 授权 - 访问控制
  • 密码加密 - 保护或隐藏数据防止被偷窥
  • 会话管理 - 每个用户相关的时间敏感的状态

1.2 Shiro 支持的辅助特性

Shiro 的存在强化了 应用安全的四要素

  • Web 应用安全
  • 单元测试
  • 多线程

2. Shiro 核心概念

Shiro 架构有三个主要概念 - Subject,SecurityManager 和 Realms。

2.1 Subject

在考虑应用安全时,你最常问的问题可能是“当前用户是谁?”或“当前用户允许做 X 吗?”。当我们写代码或设计用户界面时,问自己这些问题很平常:应用通常都是基于用户故事构建的,并且你希望功能描述(和安全)是基于每个用户的。所以,对于我们而言,考虑应用安全的最自然方式就是基于当前用户。Shiro 的 API 用它的 Subject 概念从根本上体现了这种思考方式。

Subject一词是一个安全术语,其基本意思是“当前的操作用户”。称之为“用户”并不准确,因为“用户”一词通常跟人相关。在安全领域,术语“Subject”可以是人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是 Shiro 的“用户”概念。在代码的任何地方,你都能轻易的获得 Shiro Subject

 获得 Subject
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser = SecurityUtils.getSubject();

一旦获得 Subject,你就可以立即获得你希望用 Shiro 为当前用户做的 90% 的事情,如登录、登出、访问会话、执行授权检查等 - 稍后还会看到更多。这里的关键点是 Shiro 的 API 非常直观,因为它反映了开发者以‘每个用户’思考安全控制的自然趋势。同时,在代码的任何地方都能很轻松地访问 Subject,允许在任何需要的地方进行安全操作。

2.2 Security Manager

Subject 的“幕后”推手是 SecurityManager。Subject 代表了当前用户的安全操作,SecurityManager 则管理所有用户的安全操作。它是 Shiro 框架的核心,充当“保护伞”,引用了多个内部嵌套安全组件,它们形成了对象图。但是,一旦 SecurityManager 及其内部对象图配置好,它就会退居幕后,应用开发人员几乎把他们的所有时间都花在 Subject API 调用上。

那么,如何设置 SecurityManager 呢?嗯,这要看应用的环境。例如,Web 应用通常会在 Web.xml 中指定一个 Shiro Servlet Filter,这会创建 SecurityManager 实例,如果你运行的是一个独立应用,你需要用其他配置方式,但有很多配置选项。

一个应用几乎总是只有一个 SecurityManager 实例。它实际是应用的 Singleton(尽管不必是一个静态Singleton)。跟 Shiro 里的几乎所有组件一样,SecurityManager 的缺省实现是 POJO ,而且可用 POJO 兼容的任何配置机制进行配置 - 普通的 Java 代码、Spring XML、YAML、.properties 和.ini 文件等。基本来讲,能够实例化类和调用 JavaBean 兼容方法的任何配置形式都可使用。

为此,Shiro 借助基于文本的 INI 配置提供了一个缺省的“公共”解决方案。INI 易于阅读、使用简单并且需要极少依赖。你还能看到,只要简单地理解对象导航,INI 可被有效地用于配置像 SecurityManager 那样简单的对象图。注意,Shiro 还支持 Spring XML 配置及其他方式,但这里只我们只讨论 INI。
Shiro 借助基于文本的 INI 配置提供了一个缺省的“公共”解决方案

2.3 Realms

Shiro 的第三个也是最后一个概念是Realm。Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。也就是说,当切实与像用户帐户这类安全相关数据进行交互,执行认证(登录)和授权(访问控制)时,Shiro 会从应用配置的 Realm 中查找很多内容。

从这个意义上讲,Realm 实质上是一个安全相关的 DAO :它封装了数据源的连接细节,并在需要时将相关数据提供给 Shiro。当配置 Shiro 时,你必须至少指定一个 Realm,用于认证和(或)授权。配置多个 Realm 是可以的,但是至少需要一个。

Shiro 内置了可以连接大量安全数据源(又名目录)的 Realm,如 LDAP、关系数据库(JDBC)、类似 INI 的文本配置资源以及属性文件等。如果缺省的 Realm 不能满足需求,你还可以插入代表自定义数据源的自己的 Realm 实现。

Realm 配置示例片段:连接存储用户数据的 LDAP
通过 INI 配置 Shiro 使用 LDAP 目录作为应用 Realm 的示例
[main]
ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm
ldapRealm.userDnTemplate = uid={0},ou=users,dc=mycompany,dc=com
ldapRealm.contextFactory.url = ldap://ldapHost:389
ldapRealm.contextFactory.authenticationMechanism = DIGEST-MD5 

3. 如何使用 Shiro 框架

3.1 认证

认证是核实用户身份的过程。也就是说,当用户使用应用进行认证时,他们就在证明他们就是自己所说的那个人。有时这也理解为“登录”。它是一个典型的三步骤过程。

  1. 收集用户的身份信息,称为当事人(principal),以及身份的支持证明,称为证书(Credential)
  2. 将当事人和证书提交给系统。
  3. 如果提交的证书与系统期望的该**用户身份(当事人)**匹配,该用户就被认为是经过认证的,反之则被认为未经认证的。
    这个过程的常见例子是大家都熟悉的“用户 / 密码”组合。多数用户在登录软件系统时,通常提供自己的用户名(当事人)和支持他们的密码(证书)。如果存储在系统中的密码(或密码表示)与用户提供的匹配,他们就被认为通过认证。

Shiro 以简单直观的方式支持同样的流程。正如我们前面所说,Shiro 有一个以 Subject 为中心的 API - 几乎你想要用 Shiro 在运行时完成的所有事情都能通过与当前执行的 Subject 进行交互而达成。因此,要登录 Subject,只需要简单地调用它的 login 方法,传入表示被提交当事人和证书(在这种情况下,就是用户名和密码)的 AuthenticationToken 实例。

Subject 登录 示例
//1. 接受提交的当事人和证书:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
 
//2. 获取当前 Subject:
Subject currentUser = SecurityUtils.getSubject();
//3. 登录: 
currentUser.login(token);

你可以看到,Shiro 的 API 很容易地就反映了这个常见流程。你将会在所有的 Subject 操作中继续看到这种简单风格。在调用了 login 方法后,SecurityManager 会收到 AuthenticationToken,并将其发送给已配置的 Realm,执行必须的认证检查。每个 Realm 都能在必要时对提交的 AuthenticationTokens 作出反应。但是如果登录失败了会发生什么?如果用户提供了错误密码又会发生什么?通过对 Shiro 的运行时 AuthenticationException 做出反应,你可以控制失败

 控制失败的登录 示例
//3. 登录:
try {
   currentUser.login(token);
} catch (IncorrectCredentialsException ice) {} catch (LockedAccountException lae) {}catch (AuthenticationException ae) {} 

你可以选择捕获 AuthenticationException 的一个子类,作出特定的响应,或者对任何 AuthenticationException 做一般性处理(例如,显示给用户普通的“错误的用户名或密码”这类消息)。选择权在你,可以根据应用需要做出选择。

Subject 登录成功后,他们就被认为是已认证的,通常你会允许他们使用你的应用。但是仅仅证明了一个用户的身份并不意味着他们可以对你的应用为所欲为。这就引出了另一个问题,“我如何控制用户能做或不能做哪些事情?”,决定用户允许做哪些事情的过程被称为授权。

3.2 授权

授权实质上就是访问控制 - 控制用户能够访问应用中的哪些内容,比如资源、Web 页面等等。多数用户执行访问控制是通过使用诸如角色和权限这类概念完成的。也就是说,通常用户允许或不允许做的事情是根据分配给他们的角色或权限决定的。那么,通过检查这些角色和权限,你的应用程序就可以控制哪些功能是可以暴露的。如你期望的,Subject API 让你可以很容易的执行角色和权限检查

 如何检查 Subject 被分配了某个角色
if ( subject.hasRole(“administrator”) ) {
   // 显示‘Create User’按钮
} else {
   // 按钮置灰?
} 

如你所见,你的应用程序可基于访问控制检查打开或关闭某些功能。

权限检查是执行授权的另一种方法。上例中的角色检查有个很大的缺陷:你无法在运行时增删角色。角色名字在这里是硬编码,所以,如果你修改了角色名字或配置,你的代码就会乱套!如果你需要在运行时改变角色含义,或想要增删角色,你必须另辟蹊径。

为此,Shiro 支持了权限(permissions)概念。权限是功能的原始表述,如‘开门’,‘创建一个博文’,‘删除‘jsmith’用户’等。通过让权限反映应用的原始功能,在改变应用功能时,你只需要改变权限检查。进而,你可以在运行时按需将权限分配给角色或用户

我们重写了之前的用户检查,取而代之使用权限检查
if ( subject.isPermitted(“user:create”) ) {
   // 显示‘Create User’按钮
} else {
   // 按钮置灰?
} 

这样,任何具有“user:create”权限的角色或用户都可以点击‘Create User’按钮,并且这些角色和指派甚至可以在运行时改变,这给你提供了一个非常灵活的安全模型

“user:create”字符串是一个权限字符串的例子,它遵循特定的解析惯例。Shiro 借助它的 WildcardPermission 支持这种开箱即用的惯例。尽管这超出了本文的范围,你会看到在创建安全策略时,WildcardPermission 非常灵活,甚至支持像实例级别访问控制这样的功能。

实例级别 访问控制 权限检查
if ( subject.isPermitted(“user:delete:jsmith”) ) {
   // 删除‘jsmith’用户
} else {
   // 不删除‘jsmith’
}

该例表明,你可以对你需要的单个资源进行访问控制,甚至深入到非常细粒度的实例级别。如果愿意,你甚至还可以发明自己的权限语法。参见 Shiro Permission文档可以了解更多内容。最后,就像使用认证那样,上述调用最终会转向 SecurityManager,它会咨询 Realm 做出自己的访问控制决定。必要时,还允许单个 Realm 同时响应认证和授权操作

以上就是对 Shiro 授权功能的简要概述。虽然多数安全框架止于授权和认证,但 Shiro 提供了更多功能。下面,我们将谈谈 Shiro 的高级会话管理功能。

4. 会话管理

在安全框架领域,Apache Shiro 提供了一些独特的东西:可在任何应用或架构层一致地使用 Session API**。即,Shiro 为任何应用提供了一个会话编程范式 - 从小型后台独立应用到大型集群 Web 应用。这意味着,那些希望使用会话的应用开发者,不必被迫使用 Servlet 或 EJB 容器了。或者,如果正在使用这些容器,开发者现在也可以选择使用在任何层统一一致的会话 API,取代 Servlet 或 EJB 机制。
但 Shiro 会话最重要的一个好处或许就是它们是独立于容器的。这具有微妙但非常强大的影响。例如,让我们考虑一下会话集群。对集群会话来讲,支持容错和故障转移有多少种容器特定的方式?Tomcat 的方式与 Jetty 的不同,而 Jetty 又和 Websphere 不一样,等等。但通过 Shiro 会话,你可以获得一个容器无关的集群解决方案。Shiro 的架构允许可插拔的会话数据存储,如企业缓存、关系数据库、NoSQL 系统等。这意味着,只要配置会话集群一次,它就会以相同的方式工作,跟部署环境无关 - Tomcat、Jetty、JEE 服务器或者独立应用。不管如何部署应用,毋须重新配置应用。

4.1 Subject 的会话

Shiro 会话的另一好处就是,如果需要,会话数据可以跨客户端技术进行共享。例如,Swing 桌面客户端在需要时可以参与相同的 Web 应用会话中 - 如果最终用户同时使用这两种应用,这样的功能会很有用。那你如何在任何环境中访问 Subject 的会话呢?请看下面的示例,里面使用了 Subject 的两个方法。

Subject 的会话
Session session = subject.getSession();
Session session = subject.getSession(boolean create);

4.2 会话的方法

如你所见,这些方法在概念上等同于 HttpServletRequest API。第一个方法会返回 Subject 的现有会话,或者如果还没有会话,它会创建一个新的并将之返回。第二个方法接受一个布尔参数,这个参数用于判定会话不存在时是否创建新会话。一旦获得 Shiro 的会话,你几乎可以像使用 HttpSession 一样使用它。Shiro 团队觉得对于 Java 开发者,HttpSession API 用起来太舒服了,所以我们保留了它的很多感觉。当然,最大的不同在于,你可以在任何应用中使用 Shiro 会话,不仅限于 Web 应用。下面的示例中显示了这种相似性。

会话的方法
Session session = subject.getSession();
session.getAttribute("key", someValue); 
Date start = session.getStartTimestamp();
Date timestamp = session.getLastAccessTime(); 
session.setTimeout(millis); 
...

5. 加密

加密是隐藏或混淆数据以避免被偷窥的过程。在加密方面,Shiro 的目标是简化并让 JDK 的加密支持可用。

清楚一点很重要,一般情况下,加密不是特定于 Subject 的,所以它是 Shiro API 的一部分,但并不特定于 Subject。你可以在任何地方使用 Shiro 的加密支持,甚至在不使用 Subject 的情况下。对于加密支持,Shiro 真正关注的两个领域是加密哈希(又名消息摘要)和加密密码。下面我们来看看这两个方面的详细描述。

5.1 哈希

如果你曾使用过 JDK 的 MessageDigest 类,你会立刻意识到它的使用有点麻烦。MessageDigest 类有一个笨拙的基于工厂的静态方法 API,它不是面向对象的,并且你被迫去捕获那些永远都不必捕获的 Checked Exceptions。如果需要输出十六进制编码或 Base64 编码的消息摘要,你只有靠自己 - 对上述两种编码,没有标准的 JDK 支持它们。Shiro 用一种干净而直观的哈希 API 解决了上述问题

打个比方,考虑比较常见的情况,使用 MD5 哈希一个文件,并确定该哈希的十六进制值。被称为‘校验和’,这在提供文件下载时常用到 - 用户可以对下载文件执行自己的 MD5 哈希。如果它们匹配,用户完全可以认定文件在传输过程中没有被篡改。

不使用Shiro,用 MD5 哈希一个文件,并确定该哈希的十六进制值:

  • 将文件转换成字节数组。JDK 中没有干这事的,故而你需要创建一个辅助方法用于打开 FileInputStream ,使用字节缓存区,并抛出相关的 IOExceptions,等等。
  • 使用 MessageDigest 类对字节数组进行哈希,处理相关异常
 JDK 的消息摘要
try {
   MessageDigest md = MessageDigest.getInstance("MD5");
   md.digest(bytes);
   byte[] hashed = md.digest();
} catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
} 
  • 将哈希后的字节数组编码成十六进制字符。JDK
    中还是没有干这事的,你依旧需要创建另外一个辅助方法,有可能在你的实现中会使用位操作和位移动。

对于这样简单普遍的需求,这个工作量实在太大了。

使用Shiro,用 MD5 哈希一个文件,并确定该哈希的十六进制值:

String hex = new Md5Hash(myFile).toHex(); 

当使用 Shiro 简化所有这些工作时,一切都非常简单明了。完成 SHA-512 哈希和密码的 Base64 编码也一样简单。

String encodedPassword = new Sha512Hash(password, salt, count).toBase64();

你可以看到 Shiro 对哈希和编码简化了不少,挽救了你处理在这类问题上所消耗的脑细胞。

5.2 密码

加密是使用密钥对数据进行可逆转换的加密算法。我们使用其保证数据的安全,尤其是传输或存储数据时,以及在数据容易被窥探的时候。

如果你曾经用过 JDK 的 Cryptography API,特别是 javax.crypto.Cipher 类,你会知道它是一头需要驯服的极其复杂的野兽。对于初学者,每个可能的加密配置总是由一个 javax.crypto.Cipher 实例表示。必须进行公钥 / 私钥加密?你得用 Cipher。需要为流操作使用块加密器(Block Cipher)?你得用 Cipher。需要创建一个 AES 256 位 Cipher 来保护数据?你得用 Cipher。你懂的。

那么如何创建你需要的 Cipher 实例?您得创建一个非直观、标记分隔的加密选项字符串,它被称为“转换字符串(transformation string)”,把该字符串传给 Cipher.getInstance 静态工厂方法。这种字符串方式的 cipher 选项,并没有类型安全以确保你正在用有效的选项。这也暗示没有 JavaDoc 帮你了解相关选项。并且,如果字符串格式组织不正确,你还需要进一步处理 Checked Exception,即便你知道配置是正确的。如你所见,使用 JDK Cipher 是一项相当繁重的任务。很久以前,这些技术曾经是 Java API 的标准,但是世事变迁,我们需要一种更简单的方法。

Shiro 通过引入它的 CipherService API 试图简化加密密码的整个概念。CipherService 是多数开发者在保护数据时梦寐以求的东西:简单、无状态、线程安全的 API,能够在一次方法调用中对整个数据进行加密或解密。你所需要做的只是提供你的密钥,就可根据需要加密或解密。

Shiro 使用 256 位 AES 加密
AesCipherService cipherService = new AesCipherService();
cipherService.setKeySize(256);
 
// 创建一个测试密钥: 
byte[] testKey = cipherService.generateNewKey();
// 加密文件的字节: 
byte[] encrypted = cipherService.encrypt(fileBytes, testKey);

较之 JDK 的 Cipher API,Shiro 的示例要简单的多:

  • 你可以直接实例化一个 CipherService - 没有奇怪或让人混乱的工厂方法; Cipher 配置选项可以表示成 JavaBean
  • 兼容的 getter 和 setter 方法 - 没有了奇怪和难以理解的“转换字符串”
  • 加密和解密在单个方法调用中完成
  • 没有强加的 Checked Exception。如果愿意,可以捕获 Shiro 的 CryptoException。

Shiro 的 CipherService API 还有其他好处,如同时支持基于字节数组的加密 / 解密(称为“块”操作)和基于流的加密 / 解密(如加密音频或视频)。

不必再忍受 Java Cryptography 带来的痛苦。Shiro 的 Cryptography 支持就是为了减少你在确保数据安全上付出的努力。

6. Shiro 的特性

6.1 Web 支持

最后,但并非不重要,我们将简单介绍一下 Shiro 的 Web 支持。Shiro 附带了一个帮助保护 Web 应用的强建的 Web 支持模块。对于 Web 应用,安装 Shiro 很简单。唯一需要做的就是在 web.xml 中定义一个 Shiro Servlet 过滤器。

web.xml 中的 ShiroFilter
<filter>
   <filter-name>ShiroFilter</filter-name>
   <filter-class>
        org.apache.shiro.web.servlet.IniShiroFilter
   </filter-class>
   <!-- 没有 init-param 属性就表示从 classpath:shiro.ini 装入 INI 配置 --> 
</filter>
<filter-mapping>
   <filter-name>ShiroFilter</filter-name>
   <url-pattern>/*</url-pattern> 
</filter-mapping>

这个过滤器可以读取上述 shiro.ini 配置,这样不论什么开发环境,你都拥有了一致的配置体验。一旦完成配置,Shiro Filter 就会过滤每个请求并且确保在请求期间特定请求的 Subject 是可访问的。同时由于它过滤了每个请求,你可以执行安全特定的逻辑以保证只有满足一定标准的请求才被允许通过。

6.2 URL 特定的 Filter 链

Shiro 通过其创新的 URL 过滤器链功能支持安全特定的过滤规则。它允许你为任何匹配的 URL 模式指定非正式的过滤器链。这意味着, 使用 Shiro 的过滤器机制,你可以很灵活的强制安全规则(或者规则的组合) - 其程度远远超过你单独在 web.xml 中定义过滤器时所获得的。

路径特定的 Filter 链
[urls]
/assets/** = anon
/user/signup = anon
/user/** = user
/rpc/rest/** = perms[rpc:invoke], authc
/** = authc

如你所见,**Web 应用可以使用 [urls] INI 段落。对于每一行,等号左边的值表示相对上下文的 Web 应用路径。等号右边的值定义了过滤器链 - 一个逗号分隔的有序 Servlet 过滤器列表,它会针对给出的路径进行执行。**每个过滤器都是普通的 Servlet 过滤器,你看到的上面的过滤器名字(anon,user,perms,authc)是 Shiro 内置的安全相关的特殊过滤器。你可以搭配这些安全过滤器来创建高度定制的安全体验。你还可以指定任何其他现有的 Servlet 过滤器。

相比起使用 web.xml,在其中先定义过滤器块,然后定义单独分离的过滤器模式块,这种方式带来的好处有多少?采用 Shiro 的方法,可以很容易就准确知道针对给定匹配路径执行的过滤器链。如果想这么做,你可以在 web.xml 中仅定义 Shiro Filter,在 shiro.ini 中定义所有其他的过滤器和过滤器链,这要比 web.xml 简洁得多,而且更容易理解过滤器链定义机制。即使不使用 Shiro 的任何安全特性,单凭这样小小的方便之处,也值得让你使用 Shiro。

6.3 JSP 标签库

Shiro 还提供了 JSP 标签库,允许你根据当前 Subject 的状态控制 JSP 页面的输出。一个有用的常见示例是在用户登录后显示“Hello "文本。但若是匿名用户,你可能想要显示其他内容,如换而显示“Hello! Register Today!”。

JSP 标签库示例
<%@ taglib prefix="shiro" 
  uri="http://shiro.apache.org/tags" %>
...
<p>Hello
<shiro:user> 
   <!-- shiro:principal 打印出了 Subject 的主当事人 - 在这个示例中,就是用户名: --> 
   <shiro:principal/>!
</shiro:user>
<shiro:guest> 
   <!-- 没有登录 - 就认为是 Guest。显示注册链接: --> 
   ! <a href=”register.jsp”>Register today!</a>
</shiro:guest>
</p> 

除了上面例子用到的标签,还有其他标签可以让你根据用户属于(或不属于)的角色,分配(或未分配)的权限,是否已认证,是否来自“记住我”服务的记忆,或是匿名访客,包含输出。

Shiro 还支持其他许多 Web 特性,如简单的“记住我”服务,REST 和 BASIC 认证。当然,如果想使用 Shiro 原生的企业会话,它还提供透明的 HttpSession 支持。参见 Apache Shiro Web 文档可以了解更多内容。

6.4 Web 会话管理

最后值得一提的是 Shiro 在 Web 环境中对会话的支持。
6.4.1 缺省 Http 会话

对于 Web 应用,Shiro 缺省将使用我们习以为常的 Servlet 容器会话作为其会话基础设施。即,当你调用 subject.getSession() 和 subject.getSession(boolean) 方法时,Shiro 会返回 Servlet 容器的 HttpSession 实例支持的 Session 实例。这种方式的曼妙之处在于调用 subject.getSession() 的业务层代码会跟一个 Shiro Session 实例交互 - 还没有“认识”到它正跟一个基于 Web 的 HttpSession 打交道。这在维护架构层之间的清晰隔离时,是一件非常好的事情。

6.4.2 Web 层中 Shiro 的原生会话

如果你由于需要 Shiro 的企业级会话特性(如容器无关的集群)而打开了 Shiro 的原生会话管理,你当然希望 HttpServletRequest.getSession() 和 HttpSession API 能和“原生”会话协作,而非 Servlet 容器会话。如果你不得不重构所有使用 HttpServletRequest 和 HttpSession API 的代码,使用 Shiro 的 Session API 来替换,这将非常令人沮丧。Shiro 当然从来不会期望你这么做。相反,Shiro 完整实现了 Servlet 规范中的 Session 部分以在 Web 应用中支持原生会话。这意味着,不管何时你使用相应的 HttpServletRequest 或 HttpSession 方法调用,Shiro 都会将这些调用委托给内部的原生会话 API。结果,你无需修改 Web 代码,即便是你正在使用 Shiro 的‘原生’企业会话管理 - 确实是一个非常方便(且必要)的特性。

7. 附加特性

Apache Shiro 框架还包含有对保护 Java 应用非常有用的其他特性,如:

  • 为维持跨线程的 Suject 提供了线程和并发支持(支持 Executor 和 ExecutorService)
  • 为了将执行逻辑作为一种特殊的 Subject,支持 Callable 和 Runnable 接口
  • 为了表现为另一个 Subject 的身份,支持“Run As”(比如,在管理应用中有用)
  • 支持测试工具,这样可以很容易的对 Shiro 的安全代码进行单元测试和集成测试。

8. 框架局限

常识告诉我们,Apache Shiro 不是“银弹” - 它不能毫不费力的解决所有安全问题。如下是 Shiro 还未解决,但是值得知道的

8.1 虚拟机级别的问题

Apache Shiro 当前还未处理虚拟机级别的安全,比如基于访问控制策略,阻止类加载器中装入某个类。然而,Shiro 集成现有的 JVM 安全操作并非白日做梦 - 只是没人给项目贡献这方面的工作。

8.2 多阶段认证

目前,Shiro 不支持“多阶段”认证,即用户可能通过一种机制登录,当被要求再次登录时,使用另一种机制登录。这在基于 Shiro 的应用中已经实现,但是通过应用预先收集所有必需信息再跟 Shiro 交互。这个功能在 Shiro 的未来版本中非常有可能得到支持。

8.3 Realm 写操作

目前所有 Realm 实现都支持“读”操作来获取验证和授权数据以执行登录和访问控制。诸如创建用户帐户、组和角色或与用户相关的角色组和权限这类“写”操作还不支持。这是因为支持这些操作的应用数据模型变化太大,很难为所有的 Shiro 用户强制定义“写”API。

9. 未来的特性

Apache Shiro 社区每天都在壮大,借此,Shiro 的特性亦是如此。在即将发布的版本中,你可能会看到:

  • 更干净的 Web 过滤机制,无需子类化就可支持更多的插件式过滤器。
  • 更多可插拔的缺省 Realm 实现,优先采用组合而非继承。你可以插入查找认证和授权数据的组件,无需实现为 Shiro Realm 的子类
  • 强健的 OpenID 和 OAuth (可能是混合)客户端支持
  • 支持 Captcha
  • 针对纯无状态应用的配置简化(如,许多 REST 环境)
  • 通过请求 / 响应协议进行多阶段认证
  • 通过 AuthorizationRequest 进行粗粒度的授权
  • 针对安全断言查询的 ANTLR 语法(比如,(‘role(admin) && (guest || !group(developer))’)

10. 总结

Apache Shiro 是一个功能齐全、健壮、通用的 Java 安全框架,你可以用其为你的应用护航。通过简化应用安全的四个领域,即认证、授权、会话管理和加密,在真实应用中,应用安全能更容易被理解和实现。Shiro 的简单架构和兼容 JavaBean 使其几乎能够在任何环境下配置和使用。附加的 Web 支持和辅助功能,比如多线程和测试支持,让这个框架为应用安全提供了“一站式”服务。Apache Shiro 开发团队将继续前进,精炼代码库和支持社区。随着持续被开源和商业应用采纳,可以预期 Shiro 会继续发展壮大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值