Apache shiro介绍

简介: 当你尝试保护你的程序时候你会被困扰吗?你会觉得现有的java安全方案难以使用并且将来还会困惑你?这篇文章介绍Apach shiro,一个简单而又强大的保护程序安全的安全框架。它解释了Apache的项目目标。架构原理和如何使用shiro保护你的程序。

原文链接Application Security With Apache Shiro(翻译)

前面自己自己配合谷歌翻译,后面大部分谷歌翻译。


当你尝试保护你的程序时候你会被困扰吗?你会觉得现有的java安全方案难以使用并且将来还会困惑你?这篇文章介绍Apach shiro,一个简单而又强大的保护程序安全的安全框架。它解释了Apache的项目目标。架构原理和如何使用shiro保护你的程序。


什么是shiro



shiro是强大易用的java安全框架,提供身份认证,授权,加密和会话管理(authentication, authorization, cryptography, and session management )并且能够用于任何命令行应用程序,移动应用到最大的web和企业应用。


shiro提供安全api来执行一下方面(作者喜欢把它称作程序安全的四个基石)


身份认证(Authentication)-证明用户身份,通常叫做登陆(login)。

授权(Authorization)-访问控制

加密(Cryptography)-保护或隐藏数据

会话管理(session management)每个用户时间敏感状态


shiro也支持一些辅助功能,例如 web程序安全,单元测试, 多线程支持。但是这些都是为了加强上述四个功能。


shiro咋被产生了呢(Why was Apache Shiro created?)?



对于一个真正为其存在提供良好案例的框架,因此你有理由使用它,他应该满足其他替代方案无法满足的需求,我们应该去看看shiro被创建时的历史和替代方案来理解它。


在2008进入apache之前,shiro就已经5岁了,以前被称为JSecurity project,在2003上半年完成,在2003没有太多的通用安全方案被java开发者使用。-我们坚持使用java身份验证和授权管理。尽管有JAAS,但是缺点太多了-尽管他的身份验证还能将就忍忍用着,但是授权方面真的是难用的一批并且困扰着我们,况且JAAS是严重依赖虚拟机级别的安全问题。例如,决定允许一个类在虚拟机中载入,作为一个应用开发者,我更关心的是最终用户能在程序上做什么,而不是我的代码能在JVM虚拟机中做什么。


由于当时我正在处理应用程序,我也需要一个干净的,与容器无关的会话机制。在当时的项目中唯一的会话选择就是HttpSessions,这需要一个web容器,或者需要EJB 2.1 stateful Beans,我需要一些和容器分离的东西,可以在我选择的任何环境中使用。


最后,存在加密问题,有时我们都需要保证数据传输的安全。但除非你是加密专家,否则java密码体系结构很难理解。API充满了异常并且使用起来很笨重。我希望一个更清洁的开箱即用的解决方案,可以根据需要轻松加密和解密数据。


所有在2003年早期的安全领域,你可以快速明白这儿没有任何东西能够满足指标。有凝聚力的框架,因为这个,JSecurity,还有后来的Apache shiro,诞生了。


为什么你今天会使用Apache shiro?



自从2003框架领域已经发生了巨大的变化,所以应该有令人信服的理由让人在今天还使用shiro。实际上原因很多:


容易使用-易于使用应该是项目的最终目标。应用安全可能是个极大的困扰和阻挠并且被认为是 ‘必不可少的恶魔’。如果你能使他简单并且新手程序员能够开始使用它,那么将不会有任何烦恼。


全面-shiro生称没有其他安全框架像shiro一样范围广泛,因此它可能是您的“一站式服务”来满足你的安全需求。


灵活-shiro能够在各种应用环境下工作,虽然它适合用于web,EJB,和IoC环境,但它不需要它们。shiro也没用要求强制任何规范,甚至依赖都很少。


web能力shiro有良好的web应用支持性。允许你根据URL或者web协议(例如REST)创建灵活的安全策略。同时还提供一组jsp库来控制输出。


可植入性shiro简洁的API和设计规范让它很容易整合其他框架和应用,你可以很容易看到shiro整合Spring,Grails,Wicket,Tapestry,Mule,Apache Camel,Vaadin,和许多其他。


被支持shiro是Apache 软件基金会的成员。


谁在使用shiro?



Shiro及其前身JSecurity在大小公司和企业中已经被使用多年,由于变成了一个apache的顶级项目,网站流量和采用率显著上涨,许多开源社区也在使用shiro,例如Spring, Grails, Wicket, Tapestry, Tynamo, Mule, and Vaadin,仅仅是名单的小部分。


像Katasoft,Sonatype,MuleSoft这样的主要社交网络之一的商业公司以及一些纽约商业银行使用Shiro来保护他们的商业软件和网站。


核心部分:Subject, SecurityManager, and Realms



Subject


当你保护你的程序时,你最可能会问你的问题是:“当前的使用者是谁”?或者“当前的使用着是否允许执行 X”?当我们写代码或者写用户接口时我们很容易这样问自己,应用程序通常基于用户的故事,并且你希望基于每个用户表示(和保护)功能。所以,你就会自然而然的想到基于当前用户在应用程序中的安全性,shiro的API的Subject概念从根本上代表这种思维。


subject代表“当前操作的对象”,他不是‘User’因为user通常代表一个人。你可以把它当成shiro的user对象。


listing 1,获得Subject对象。


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


一旦你获得Subject对象,你立马能够为当前user在shiro中做90%你想做的事情,比如login,logout,获取session,执行授权检查等等,但是在这之后,这里的关键的是Shiro的API在很大程度是直观的,因为它反应了开发人员在“per-user”安全控制中的思考。当然在代码的任何地方获取Subject也是容易的,允许在需要安全的地方进行任何安全操作。


SecurityManager


Subject的幕后对应物应该是SecurityManager。当Subject代表当前user的安全操作时SecurityManager管理所有user的安全操作,他是shiro的核心架构,充当一种“伞形”对象,它引用了许多形成对象图的内部嵌套安全组件。 但是,一旦配置了SecurityManager及其内部对象图,通常就会将其保留,应用程序开发人员几乎将所有时间花在Subject API上。


所以你将如何创建一个SecurityManager?当然,它基于应用的环境,比如 一个web程序通常指定一个shiro servlet filter在web.xml,这将建立SecurityManager实例。


每个应用程序几乎总是有一个SecurityManager实例,他本质上是一个应用程序单例(尽管它不需要静态单例),与shiro中所有事情几乎一致,默认的SecurityManager实现是POJO,可以使用任何兼容POJO的配置机制进行配置 - 普通Java代码,Spring XML,YAML,.properties和.ini文件等。基本上任何能够实例化类的东西 并且可以使用调用JavaBeans兼容的方法。


最后,Shiro通过基于文本的INI配置提供默认的“公分母”解决方案。 INI易于阅读,易于使用,并且需要很少的依赖性。 您还将看到,通过对对象图导航的简单理解,可以有效地使用INI来配置像SecurityManager这样的简单对象图。 请注意,Shiro还支持Spring XML配置和其他替代方案,但我们将在此处介绍INI。


Listing 2. Configuring Shiro with INI


[main]
cm = org.apache.shiro.authc.credential.HashedCredentialsMatcher
cm.hashAlgorithm = SHA-512
cm.hashIterations = 1024
# Base64 encoding (less text):
cm.storedCredentialsHexEncoded = false


iniRealm.credentialsMatcher = $cm


[users]
jdoe = TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJpcyByZWFzb2
asmith = IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbXNoZWQsIG5vdCB


在list2中,我们将看到用于配置SecurityManager实例的示例INI配置。 有两个INI部分:[main]和[users]。


[main]部分用于配置SecurityManager对象和/或SecurityManager使用的任何对象(如Realms)。 在此示例中,我们看到正在配置两个对象:


  1. cm对象,是Shiro的HashedCredentialsMatcher类的一个实例。 如您所见,cm实例的各种属性正在通过’嵌套点’语法(清单3中所示的IniSecurityManagerFactory使用的约定)来配置,以表示对象图导航和属性设置。
  2. iniRealm对象,它是SecurityManager用于表示以INI格式定义的用户帐户的组件。

您可以在[users]部分指定用户帐户的静态列表 - 方便简单应用程序或测试时。


出于本简介的目的,理解每个部分的复杂性并不重要,而是要看INI配置是配置Shiro的一种简单方法。 有关INI配置的更多详细信息,请参阅Shiro的文档。


Listing 3. Loading shiro.ini Configuration File


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.util.Factory;
---
---
...
//1. Load the INI configuration
Factory factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
//2. Create the SecurityManager
SecurityManager securityManager = factory.getInstance();
//3. Make it accessible
SecurityUtils.setSecurityManager(securityManager);


在list3,我们看到一个简单例子的三个步骤。


装载INI配置文件它将配置SecurityManager和他的组件。

根据配置创建SecurityManager实例(使用代表工厂方法设计模式的Shiro工厂概念)。

使应用程序可以访问SecurityManager单例。 在这个简单的示例中,我们将其设置为VM静态单例,但这通常不是必需的 - 您的应用程序配置机制可以确定您是否需要使用静态内存。


Realms


Shiro的第三个也是最后一个核心概念是一个领域。 Realm充当Shiro与应用程序安全数据之间的“桥接”或“连接器”。 也就是说,当实际与安全相关的数据(如用户帐户)进行交互以执行身份验证(登录)和授权(访问控制)时,Shiro会从为应用程序配置的一个或多个领域中查找许多这些内容。


从这个意义上讲,Realm本质上是一个特定于安全性的DAO:它封装了数据源的连接细节,并根据需要使相关数据可用于Shiro。 配置Shiro时,必须至少指定一个Realm用于身份验证和/或授权。 可以配置多个Realm,但至少需要一个。


Shiro提供了开箱即用的Realms,可以连接到许多安全数据源(也称为目录),如LDAP,关系数据库(JDBC),文本配置源(如INI和属性文件等)。 如果默认域不符合您的需要,您可以插入自己的Realm实现来表示自定义数据源。 下面的list4是配置Shiro(通过INI)将LDAP目录用作应用程序领域之一的示例。


Listing 4. Example realm configuration snippet to connect to LDAP user data store


[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 


现在我们已经了解了如何设置基本的Shiro环境,让我们讨论一下,作为开发人员,您将如何使用该框架。


Authentication


身份验证是验证用户身份的过程。 也就是说,当用户使用应用程序进行身份验证时,他们证明他们实际上是他们所说的人。 这有时也被称为“登录”。 这通常是一个三步过程。


收集用户的标识信息,称为主体,并支持身份证明,称为凭证。

将主体和凭据提交给系统。

如果提交的凭据与系统对该用户标识(主体)的期望值匹配,则认为该用户已通过身份验证。 如果它们不匹配,则不会将用户视为已通过身份验证。

每个人都熟悉的这个过程的一个常见例子是用户名/密码组合。 当大多数用户登录软件应用程序时,他们通常会提供用户名(主体)和支持密码(凭证)。 如果存储在系统中的密码(或其表示)与用户指定的密码匹配,则认为它们已经过身份验证。


Shiro以简单直观的方式支持相同的工作流程。 正如我们所说,Shiro有一个以Subject为中心的API - 几乎所有你在运行时用Shiro做的事都是通过与当前正在执行的Subject进行交互来实现的。 因此,要登录Subject,只需调用其登录方法,传递一个AuthenticationToken实例,该实例表示提交的主体和凭据(在本例中为用户名和密码)。 此示例如下面的list5所示。


Listing 5. Subject Login


//1. Acquire submitted principals and credentials:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
//2. Get the current Subject:
Subject currentUser = SecurityUtils.getSubject();
//3. Login:
currentUser.login(token);


如您所见,Shiro的API很容易反映出常见的工作流程。 您将继续将此简单性视为所有Subject操作的主题。 调用login方法时,SecurityManager将接收AuthenticationToken并将其分派给一个或多个已配置的域,以允许每个域根据需要执行身份验证检查。 每个Realm都能够根据需要对提交的AuthenticationTokens做出反应。 但是如果登录尝试失败会发生什么? 如果用户指定了错误的密码该怎么办? 您可以通过对Shiro的运行时AuthenticationException作出反应来处理故障,如list6所示。


Listing 6. Handle Failed Login


//3. Login:
try {
 currentUser.login(token);
} catch (IncorrectCredentialsException ice) { …
} catch (LockedAccountException lae) { …
}
catch (AuthenticationException ae) {…
} 


您可以选择捕获其中一个AuthenticationException子类并进行具体反应,或者通常处理任何AuthenticationException(例如,向用户显示通用的“不正确的用户名或密码”消息)。 根据您的应用要求,您可以选择。


在成功登录主题后,它们将被视为已通过身份验证,通常您允许它们使用您的应用程序。 但仅仅因为用户证明了他们的身份并不意味着他们可以在您的应用程序中做任何他们想做的事情。 这引出了下一个问题,“我如何控制允许用户做什么?”决定允许用户做什么称为授权。 我们将介绍Shiro如何启用授权。


Authorization


授权本质上是访问控制 - 控制用户可以在应用程序中访问的内容,例如资源,网页等。大多数用户通过使用角色和权限等概念来执行访问控制。 也就是说,通常允许用户基于分配给他们的角色和/或许可来做某事或不做某事。 然后,您的应用程序可以根据对这些角色和权限的检查来控制公开的功能。 正如您所料,Subject API允许您非常轻松地执行角色和权限检查。 例如,list7中的代码片段显示了如何检查Subject是否已分配了某个角色。


Listing 7. Role Check


if ( subject.hasRole(“administrator”) ) {
 //show the ‘Create User’ button
} else {
 //grey-out the button?
} 


如您所见,您的应用程序可以根据访问控制检查启用或禁用功能。


权限检查是执行授权的另一种方式。 检查上面示例中的角色会遇到一个重大缺陷:您无法在运行时添加或删除角色。 您的代码使用角色名称进行了硬编码,因此如果您更改了角色名称和/或配置,您的代码就会被破坏! 如果您需要能够在运行时更改角色的含义,或者根据需要添加或删除角色,则必须依赖其他内容。


为此,Shiro支持其权限概念。 权限是一个原始的功能声明,例如“打开一扇门”,“创建一个博客条目”,“删除’jsmith’用户’等。通过拥有反映应用程序原始功能的权限,您只需要更改权限 更改应用程序的功能时检查。 反过来,您可以在运行时根据需要为角色或用户分配权限。


作为一个例子,如下面的list8所示,我们可以重写之前的角色检查,而是使用权限检查。


Listing 8. Permission Check


if ( subject.isPermitted(“user:create”) ) {
 //show the ‘Create User’ button
} else {
 //grey-out the button?
} 


这样,任何分配了“user:create”权限的角色或用户都可以单击“创建用户”按钮,这些角色和分配甚至可以在运行时更改,为您提供非常灵活的安全模型。


“user:create”字符串是遵循某些解析约定的权限字符串的示例。 Shiro通过WildcardPermission开箱即用,支持这种约定。 虽然超出了本介绍文章的范围,但您会看到WildcardPermission在创建安全策略时可以非常灵活,甚至可以支持实例级访问控制等内容。


Listing 9. Instance-Level Permission Check


if ( subject.isPermitted(“user:delete:jsmith”) ) {
 //delete the ‘jsmith’ user
} else {
 //don’t delete ‘jsmith’
}


此示例显示,如果需要,您甚至可以控制对非常细粒度的实例级别的访问。 如果您愿意,您甚至可以创建自己的权限语法。 有关更多信息,请参阅Shiro权限文档。 最后,就像身份验证一样,上述调用最终会进入SecurityManager,它将咨询一个或多个Realms以做出访问控制决策。 这允许Realm根据需要响应身份验证和授权操作。


这是对Shiro授权功能的简要概述。 虽然大多数安全框架都停止了身份验证和授权,但Shiro提供了更多功能。 接下来我们将讨论Shiro的高级会话管理功能。


Session Management


Apache Shiro在安全框架领域提供了独特的东西:一致的会话session API,可用于任何应用程序和任何架构层。 也就是说,Shiro为任何应用程序启用了会话编程范例 - 从小型守护程序独立应用程序到最大的集群Web应用程序。 这意味着希望使用会话的应用程序开发人员不再需要使用Servlet或EJB容器,否则就不需要它们。 或者,如果使用这些容器,开发人员现在可以选择在任何层中使用统一且一致的会话API,而不是servlet或EJB特定的机制。


但也许Shiro session会话最重要的好处之一就是它们与容器无关。 这具有微妙但极其强大的含义。 例如,让我们考虑会话群集。 有多少特定于容器的方法来集群会话以进行容错和故障转移? Tomcat的做法与Jetty有所不同,它与Websphere等不同。但是通过Shiro会话,您可以获得与容器无关的群集解决方案。 Shiro的架构允许可插入的Session数据存储,例如企业缓存,关系数据库,NoSQL系统等。 这意味着您可以配置一次会话群集,无论您的部署环境如何,它都将以相同的方式工作 - Tomcat,Jetty,JEE Server或独立应用程序。 无需根据部署应用程序的方式重新配置应用程序。


Shiro会话的另一个好处是,如果需要,可以跨客户端技术共享会话数据。 例如,如果需要,Swing桌面客户端可以参与同一个Web应用程序会话 - 如果最终用户同时使用两者,则会很有用。 那么如何在任何环境中访问主题会话? 有两种主题方法,如下例所示。


Listing 10. Subject’s Session


Session session = subject.getSession();
Session session = subject.getSession(boolean create);


如您所见,这些方法在概念上与HttpServletRequest API相同。 第一种方法将返回Subject的现有Session,或者如果还没有,它将创建一个新的并返回它。 第二种方法接受一个布尔参数,该参数确定是否将创建新的Session(如果它尚不存在)。 获得Subject会话后,您几乎可以使用它与HttpSession相同。 Shiro团队认为HttpSession API对Java开发人员来说最为舒适,因此我们保留了很多感觉。 当然,最大的区别在于您可以在任何应用程序中使用Shiro Sessions,而不仅仅是Web应用程序。 list11显示了这种熟悉程度。


Listing 11. Session methods


Session session = subject.getSession();
session.getAttribute(“key”, someValue);
Date start = session.getStartTimestamp();
Date timestamp = session.getLastAccessTime();
session.setTimeout(millis);


Cryptography


密码学是隐藏或混淆数据的过程,因此窥探眼睛无法理解它。 Shiro在加密方面的目标是简化并使JDK的加密支持变得可用。


重要的是要注意密码学一般不是特定于受试者,因此它是Shiro API的一个非特定Subject的区域。 您可以在任何地方使用Shiro的加密支持,即使没有使用Subject。 Shiro真正关注其加密支持的两个领域是加密哈希(也称为消息摘要)和加密密码。 让我们更详细地看一下这两个。


Hashing


如果您使用过JDK的MessageDigest类,您很快就会意识到使用它有点麻烦。 它有一个笨拙的静态方法基于工厂的API而不是面向对象的API,你被迫捕获可能永远不需要捕获的已检查异常。 如果您需要十六进制编码或Base64编码消息摘要输出,您可以自己 - 没有标准的JDK支持。 Shiro使用简洁直观的散列API解决了这些问题。


例如,让我们考虑相对常见的MD5散列文件并确定该散列的十六进制值的情况。 称为“校验和”,在提供文件下载时会定期使用 - 用户可以在下载的文件上执行自己的MD5哈希,并声明其校验和与下载站点上的校验和匹配。 如果它们匹配,则用户可以充分地假设文件在传输中未被篡改。


如果没有Shiro,您可以尝试这样做:


将文件转换为字节数组。 JDK中没有任何内容可以帮助解决这个问题,因此您需要创建一个帮助方法来打开FileInputStream,使用字节缓冲区,并抛出相应的IOExceptions等。


使用MessageDigest类来散列字节数组,处理相应的异常,如下面的list12所示。

将散列字节数组编码为十六进制字符。 JDK中没有任何东西可以帮助解决这个问题,因此您需要创建另一个辅助方法,并且可能在实现中使用按位运算和位移。


Listing 12. JDK’s MessageDigest


try {
 MessageDigest md = MessageDigest.getInstance("MD5");
 md.digest(bytes);
 byte[] hashed = md.digest();
} catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
} 


这对于如此简单和相对常见的事情来说是一项重要的工作。 现在,这里是如何与Shiro完全相同的事情。


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


当您使用Shiro简化所有工作时,它会变得非常简单和容易理解。 SHA-512哈希和密码的Base64编码同样简单。


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


您可以看到Shiro简化了散列和编码的程度,在此过程中为您节省了一些理智。


Ciphers


密码是加密算法,可以使用密钥可逆地转换数据。 我们使用它们来保证数据安全,特别是在传输或存储数据时,数据特别容易被窥探的时候。


如果你曾经使用过JDK Cryptography API,特别是javax.crypto.Cipher类,你知道它可能是一个令人难以置信的复杂野兽。 对于初学者,每个可能的密码配置总是由javax.crypto.Cipher的实例表示。 需要做公钥/私钥加密吗? 您使用密码。 需要使用Block Cipher进行流媒体操作吗? 您使用密码。 需要创建AES 256位密码来保护数据? 您使用密码。 你明白了。


您如何创建所需的Cipher实例? 您创建了一个复杂的,不直观的以令牌分隔的密码选项字符串,称为“转换字符串”,并将此字符串传递给Cipher.getInstance静态工厂方法。 使用此密码选项字符串方法,没有类型安全性来确保您使用有效选项。 这也隐含地意味着没有JavaDoc来帮助您理解相关选项。 如果您的String配置不正确,即使您知道配置正确,您还需要处理已检查的异常。 如您所见,使用JDK Ciphers是一项非常繁琐的任务。 这些技术很久以前就已成为Java API的标准,但时代已经发生变化,我们想要一种更简单的方法。


Shiro试图通过引入其CipherService API来简化加密密码的整个概念。 CipherService是大多数开发人员在保护数据时所需要的:一个简单的,无状态的,线程安全的API,可以在一个方法调用中完整地加密或解密数据。 您需要做的就是提供密钥,您可以根据需要进行加密或解密。 例如,可以使用256位AES加密,如下面的list13所示。


Listing 13. Apache Shiro’s Encryption API


AesCipherService cipherService = new AesCipherService();
cipherService.setKeySize(256);
//create a test key:
byte[] testKey = cipherService.generateNewKey();
//encrypt a file’s bytes:
byte[] encrypted =
 cipherService.encrypt(fileBytes, testKey);


与JDK的Cipher API相比,Shiro示例更简单:


您可以直接实例化CipherService - 没有奇怪或令人困惑的工厂方法。

密码配置选项表示为兼容JavaBeans的getter和setter - 没有奇怪且难以理解的“转换字符串”。

加密和解密在单个方法调用中执行。

没有强制检查异常。 如果你愿意,可以抓住Shiro的CryptoException。

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


Java密码学不需要痛苦。 Shiro的加密支持旨在简化您保护数据安全的工作。


Web Support


最后,但并非最不重要的是,我们将简要介绍Shiro的web支持。 Shiro附带强大的Web支持模块,可帮助保护Web应用程序。 为Web应用程序设置Shiro很简单。 唯一需要的是在web.xml中定义Shiro Servlet过滤器。 list14显示了此代码。


Listing 14. ShiroFilter in web.xml


 ShiroFilter</filter-name>
 org.apache.shiro.web.servlet.IniShiroFilter
 </filter-class>
</filter>
 ShiroFilter</filter-name>
 /*</url-pattern>
</filter-mapping>


此过滤器可以读取前面提到的shiro.ini配置,因此无论部署环境如何,您都可以获得一致的配置体验。 配置完成后,Shiro过滤器将过滤每个请求,并确保在请求期间可以访问特定于请求的主题。 并且因为它会过滤每个请求,您可以执行特定于安全性的逻辑,以确保只允许满足特定条件的请求。


URL-Specific Filter Chains


Shiro通过其创新的URL过滤器链接功能支持特定于安全性的过滤规则。 它允许您为任何匹配的URL模式指定ad-hoc过滤器链。 这意味着您可以使用Shiro的过滤机制在执行安全规则(或规则组合)方面具有很大的灵活性 - 远远超过您可以单独在web.xml中定义过滤器。 list15显示了Shiro INI中的配置代码段。


Listing 15. Path-specific Filter Chains


[urls]
/assets/** = anon
/user/signup = anon
/user/** = user
/rpc/rest/** = perms[rpc:invoke], authc
/** = authc


如您所见,Web应用程序可以使用[urls] INI部分。 对于每一行,等号左侧的值表示与上下文相关的Web应用程序路径。 右侧的值定义了一个Filter链 - 一个有序的逗号分隔的Servlet过滤器列表,用于给定路径执行。 每个过滤器都是一个普通的Servlet过滤器,但您在上面看到的过滤器名称(anon,user,perms,authc)是Shiro提供的特殊安全相关过滤器。 您可以混合和匹配这些安全筛选器,以创建非常自定义的安全体验。 您还可以指定您可能拥有的任何其他现有Servlet过滤器。


与使用web.xml相比,这有多好,在这里您定义了一个过滤器块,然后是一个单独的断开的过滤器模式块? 使用Shiro的方法,更容易看到为给定匹配路径执行的过滤器链。 如果您愿意,您可以在web.xml中仅定义Shiro Filter,并在shiro.ini中定义所有其他过滤器和过滤器链,以获得比web.xml更简洁易懂的过滤器链定义机制。 即使您没有使用Shiro的任何安全功能,仅此一个小便利就可以使Shiro值得使用。


JSP Tag Library


Shiro还提供了一个JSP标记库,允许您根据当前Subject的状态控制JSP页面的输出。 这有用的一个常见示例是在用户登录后显示“Hello ”文本。 但如果他们是匿名的,你可能想要展示别的东西,比如“你好! 立即注册!“相反。 list16显示了如何使用Shiro的JSP标记来支持它。


Listing 16. JSP Taglib Example


<%@ taglib prefix="shiro"
 uri="http://shiro.apache.org/tags" %>
...
 Hello
 !
</shiro:user>
 ! Register today!</a>
</shiro:guest>
</p> 


还有其他标记允许您根据他们拥有(或没有)的角色,分配(或未分配)的权限以及是否通过“记住我”服务记住它们,或者记住它们来包含输出 匿名客人。


Shiro支持许多其他特定于Web的功能,例如简单的“记住我”服务,REST和BASIC身份验证,当然还有透明的HttpSession支持,如果您想使用Shiro的本机企业会话。 有关更多信息,请参阅Apache Shiro Web文档。


Web Session Management


最后,有趣的是指出Shiro对Web环境中的会话的支持。


Default Http Sessions


对于Web应用程序,Shiro默认其会话基础结构使用我们以前习惯的现有Servlet容器会话。 也就是说,当你调用方法subject.getSession()和subject.getSession(boolean)时,Shiro将返回由Servlet容器的HttpSession实例支持的Session实例。 这种方法的优点在于调用subject.getSession()的业务层代码与Shiro Session实例交互 - 它没有“知识”它正在使用基于Web的HttpSession对象。 在跨建筑层保持清洁分离时,这是一件非常好的事情。


Shiro’s Native Sessions in the Web Tier


如果您已经在Web应用程序中启用了Shiro的本机会话管理,因为您需要Shiro的企业会话功能(如与容器无关的群集),您当然希望HttpServletRequest.getSession()和HttpSession API与“本机”会话一起使用,不是servlet容器会话。如果你必须重构任何使用HttpServletRequest和HttpSession API的代码来改为使用Shiro的Session API,那将是非常令人沮丧的。 Shiro当然不会指望你这样做。相反,Shiro完全实现了Servlet规范的Session部分,以支持Web应用程序中的本机会话。这意味着无论何时调用相应的HttpServletRequest或HttpSession方法调用,Shiro都会将这些调用委托给其内部本地Session API。最终结果是,即使您正在使用Shiro的“本机”企业会话管理,您也不必更改您的Web代码 - 这确实是一个非常方便(和必要)的功能。


Additional Features


Apache Shiro框架中还有其他一些对保护Java应用程序有用的功能,例如:


跨线程维护主题的线程和并发支持(Executor和ExecutorService支持)

Callable和Runnable支持将逻辑作为特定主题执行

“运行为”支持假设另一个主题的身份(例如在管理应用程序中有用)

测试线束支持,使得在单元和集成测试中完全测试Shiro安全代码非常容易


Framework Limitations


尽管我们可能会喜欢它,但Apache Shiro并不是一个“银弹” - 它无法毫不费力地解决所有安全问题。 Shiro没有提到可能值得了解的事情:


虚拟机级别问题:Apache Shiro目前不处理虚拟机级安全性,例如能够根据访问控制策略阻止某些类在类加载器中加载。但是,Shiro可以与现有的JVM安全操作集成并不是不可想象的 - 只是没有人为项目贡献过这样的工作。


多阶段身份验证:Shiro目前本身不支持“多阶段”身份验证,用户可以通过一种机制登录,只是被要求再使用不同的机制登录。这已经在基于Shiro的应用程序中完成,但是应用程序预先收集所有必需的信息,然后与Shiro交互。很有可能在未来的Shiro版本中支持此功能。


Realm写入操作:目前,所有领域实现都支持“读取”操作,用于获取身份验证和授权数据以执行登录和访问控制。不支持“写入”操作,如创建用户帐户,组和角色,或者将用户与角色组和权限相关联。这是因为支持这些操作的数据模型在不同应用程序之间存在很大差异,并且很难在所有Shiro用户上强制执行“写入”API。


Upcoming Features


Apache Shiro的社区每天都在不断发展,有了它,Shiro的功能也是如此。 在即将推出的版本中,您可能会看到:


更清晰的Web过滤机制,允许更多的可插入过滤支持,无需子类化。

更多可插入的默认Realm实现更有利于组合而不是继承。 您将能够插入查找身份验证和授权数据的组件,而不是要求您继承Shiro Realm实现

强大的OpenID和OAuth(以及可能的混合)客户端支持


Captcha支持


更轻松地配置100%无状态应用程序(例如,许多REST环境)。

通过请求/响应协议进行多阶段身份验证。

通过AuthorizationRequest进行粗粒度授权。

安全断言查询的ANTLR语法(例如(‘role(admin)&&(guest ||!group(developer))’)


Summary


Apache Shiro是一个功能齐全,功能强大且通用的Java安全框架,可用于保护应用程序。 通过简化应用程序安全性的四个方面,即身份验证,授权,会话管理和加密,应用程序安全性在实际应用程序中更容易理解和实现。 Shiro的简单架构和JavaBeans兼容性使其几乎可以在任何环境中进行配置和使用。 额外的Web支持和辅助功能(如多线程和测试支持)使框架更加完善,可以为应用程序安全提供“一站式服务”。 Apache Shiro的开发团队继续向前发展,完善代码库并支持社区。 随着持续的开源和商业应用,Shiro预计只会变得更强大。


Resources


Apache Shiro的主页。


Shiro的下载页面,包含Maven和Ant Ivy用户的其他信息。


Apache Shiro的文档页面,包含指南和参考手册


由项目的PMC主席Les Hazlewood提供的Apache Shiro演示视频和幻灯片。


其他Apache Shiro文章和演示文稿


Apache Shiro邮件列表和论坛。


Katasoft - 一家提供Apache Shiro专业支持和应用程序安全产品的公司。


目录
相关文章
|
安全 算法 Oracle
【WEB安全】Apache Shiro 反序列化漏洞(上)
Apache Shiro是一款开源企业常见JAVA安全框架,提供身份验证、授权、密码学和会话管理。java中的权限框架有SpringSecurity和Shiro,由于Spring功能强大但复杂,Shiro的简单强大,扩展性好因此用的还是很多。
613 0
【WEB安全】Apache Shiro 反序列化漏洞(上)
|
7月前
|
存储 安全 Java
【Shiro】Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437)的解决方案
【Shiro】Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437)的解决方案
149 0
|
12月前
|
安全 Apache 数据安全/隐私保护
Apache Shiro < 1.7.0 权限绕过漏洞集合
今天发现阿里云服务器出现了告警: shiro 1.3.2 进程ID:3932 路径:xxx\shiro-core-1.3.2.jar 命中:shiro version less than 1.7.0 网上一搜,找到了如下资料: 2020年11月2日,阿里云应急响应中心监测到Apache Shiro官方发布安全更新,修复了一个最新权限绕过漏洞。攻击者利用该漏洞可以绕过验证访问到后台功能,风险较高
268 0
|
存储 缓存 安全
Apache Shiro身份认证过程详解
Apache Shiro身份认证过程详解
200 0
Apache Shiro身份认证过程详解
|
NoSQL Java Apache
SpringBoot搭建基于Apache Shiro+Redis的分布式Session共享功能
我们在上一遍文档中已经完成了Shiro验证功能。(http://www.cnblogs.com/nbfujx/p/7773789.html),在此基础上我们将完成分布式Session共享功能。 Redis的使用 Maven Plugin添加Redis相关jar包 1 2 org.
4788 0
|
网络安全 Apache 网络架构
Apache Shiro内置过滤器
shiro内置过滤器研究   anon org.apache.shiro.web.filter.authc.AnonymousFilter authc org.apache.shiro.
733 0
|
缓存 安全 Java
这么直观、易用的 Apache Shiro,你不知道吗
Apache Shiro 是一个开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro 框架具有直观、易用等特性,同时也能提供健壮的安全性,虽然它的功能不如 SpringSecurity 那么强大,但是在普通的项目中也够用了。
这么直观、易用的 Apache Shiro,你不知道吗
|
安全 Oracle 关系型数据库
【WEB安全】Apache Shiro 反序列化漏洞(下)
Apache Shiro是一款开源企业常见JAVA安全框架,提供身份验证、授权、密码学和会话管理。java中的权限框架有SpringSecurity和Shiro,由于Spring功能强大但复杂,Shiro的简单强大,扩展性好因此用的还是很多。
323 0
【WEB安全】Apache Shiro 反序列化漏洞(下)
|
安全 Java Shell
【WEB安全】Apache Shiro 反序列化漏洞(中)
Apache Shiro是一款开源企业常见JAVA安全框架,提供身份验证、授权、密码学和会话管理。java中的权限框架有SpringSecurity和Shiro,由于Spring功能强大但复杂,Shiro的简单强大,扩展性好因此用的还是很多。
417 0
【WEB安全】Apache Shiro 反序列化漏洞(中)

推荐镜像

更多