在尝试保护你的应用时,你是否有过挫败感?是否觉得现有的Java安全解决方案难以使用,只会让你更糊涂?本文介绍的Apache Shiro,是一个不同寻常的Java安全框架,为保护应用提供了简单而强大的方法。本文还解释了Apache Shiro的项目目标、架构理念以及如何使用Shiro为应用安全保驾护航。
什么是Apache Shiro?Apache Shiro(发音为“shee-roh”,日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。
Shiro为解决下列问题(我喜欢称它们为应用安全的四要素)提供了保护应用的API:
相关厂商内容
Windows Azure在中国正式开启在线直付 率先在国内落地的全球化云服务,深度了解Windows Azure 利用开发测试云实现精益创业、快速迭代 Windows Azure自管理服务实现近乎零停机维护 Windows Azure专区上线,全面了解云服务 相关赞助商
Windows Azure专区上线,全面了解云服务精彩呈现!
•认证 - 用户身份识别,常被称为用户“登录”;
•授权 - 访问控制;
•密码加密 - 保护或隐藏数据防止被偷窥;
•会话管理 - 每用户相关的时间敏感的状态。
Shiro还支持一些辅助特性,如Web应用安全、单元测试和多线程,它们的存在强化了上面提到的四个要素。
[b]为何要创建Apache Shiro?[/b]
对于一个框架来讲,使其有存在价值的最好例证就是有让你去用它的原因,它应该能完成一些别人无法做到的事情。要理解这一点,需要了解Shiro的历史以及创建它时的其他替代方法。
在2008年加入Apache软件基金会之前,Shiro已经5岁了,之前它被称为JSecurity项目,始于2003年初。当时,对于Java应用开发人员而言,没有太多的通用安全替代方案 - 我们被Java认证/授权服务(或称为JAAS)紧紧套牢了。JAAS有太多的缺点 - 尽管它的认证功能尚可忍受,但授权方面却显得拙劣,用起来令人沮丧。此外,JAAS跟虚拟机层面的安全问题关系非常紧密,如判断JVM中是否允许装入一个类。作为应用开发者,我更关心应用最终用户能做什么,而不是我的代码在JVM中能做什么。
由于当时正从事应用开发,我也需要一个干净、容器无关的会话机制。在当时,“这场游戏”中唯一可用的会话是HttpSessions,它需要Web容器;或是EJB 2.1里的有状态会话Bean,这又要EJB容器。而我想要的一个与容器脱钩、可用于任何我选择的环境中的会话。
最后就是加密问题。有时,我们需要保证数据安全,但是Java密码架构(Java Cryptography Architecture)让人难以理解,除非你是密码学专家。API里到处都是Checked Exception,用起来很麻烦。我需要一个干净、开箱即用的解决方案,可以在需要时方便地对数据加密/解密。
于是,纵观2003年初的安全状况,你会很快意识到还没有一个大一统的框架满足所有上述需求。有鉴于此,JSecurity(即之后的Apache Shiro)诞生了。
[b]今天,你为何愿意使用Apache Shiro?[/b]
从2003年至今,框架选择方面的情况已经改变了不少,但今天仍有令人信服的理由让你选择Shiro。其实理由相当多,Apache Shiro:
•易于使用 - 易用性是这个项目的最终目标。应用安全有可能会非常让人糊涂,令人沮丧,并被认为是“必要之恶”【译注:比喻应用安全方面的编程。】。若是能让它简化到新手都能很快上手,那它将不再是一种痛苦了。
•广泛性 - 没有其他安全框架可以达到Apache Shiro宣称的广度,它可以为你的安全需求提供“一站式”服务。
•灵活性 - Apache Shiro可以工作在任何应用环境中。虽然它工作在Web、EJB和IoC环境中,但它并不依赖这些环境。Shiro既不强加任何规范,也无需过多依赖。
•Web能力 - Apache Shiro对Web应用的支持很神奇,允许你基于应用URL和Web协议(如REST)创建灵活的安全策略,同时还提供了一套控制页面输出的JSP标签库。
•可插拔 - Shiro干净的API和设计模式使它可以方便地与许多的其他框架和应用进行集成。你将看到Shiro可以与诸如Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin这类第三方框架无缝集成。
•支持 - Apache Shiro是Apache软件基金会成员,这是一个公认为了社区利益最大化而行动的组织。项目开发和用户组都有随时愿意提供帮助的友善成员。像Katasoft这类商业公司,还可以给你提供需要的专业支持和服务。
[b]谁在用Shiro?[/b]
Shiro及其前身JSecurity已被各种规模和不同行业的公司项目采用多年。自从成为Apache软件基金会的顶级项目后,站点流量和使用呈持续增长态势。许多开源社区也正在用Shiro,这里有些例子如Spring,Grails,Wicket,Tapestry,Tynamo,Mule和Vaadin。
如Katasoft,Sonatype,MuleSoft这样的商业公司,一家大型社交网络和多家纽约商业银行都在使用Shiro来保护他们的商业软件和站点。
核心概念:Subject,SecurityManager和Realms既然已经描述了Shiro的好处,那就让我们看看它的API,好让你能够有个感性认识。Shiro架构有三个主要概念 - Subject,SecurityManager和Realms。
Subject在考虑应用安全时,你最常问的问题可能是“当前用户是谁?”或“当前用户允许做X吗?”。当我们写代码或设计用户界面时,问自己这些问题很平常:应用通常都是基于用户故事构建的,并且你希望功能描述(和安全)是基于每个用户的。所以,对于我们而言,考虑应用安全的最自然方式就是基于当前用户。Shiro的API用它的Subject概念从根本上体现了这种思考方式。
Subject一词是一个安全术语,其基本意思是“当前的操作用户”。称之为“用户”并不准确,因为“用户”一词通常跟人相关。在安全领域,术语“Subject”可以是人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。在代码的任何地方,你都能轻易的获得Shiro Subject,参见如下代码:
清单1. 获得Subject
[url=http://shiro.apache.org/documentation.html]Shiro文档[/url]。
清单3. 装入shiro.ini配置文件
[url=http://en.wikipedia.org/wiki/Factory_method_pattern]工厂方法设计模式[/url]);
[*]使应用可访问SecurityManager Singleton。在这个简单示例中,我们将它设置为VM静态Singleton,但这通常不是必须的 - 你的应用配置机制可以决定你是否需要使用静态存储。[/*]
[/list]
[h2]Realms[/h2]
Shiro的第三个也是最后一个概念是[b]Realm[/b]。Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当切实与像用户帐户这类安全相关数据进行交互,执行认证(登录)和授权(访问控制)时,Shiro会从应用配置的Realm中查找很多内容。
从这个意义上讲,Realm实质上是一个安全相关的[url=http://en.wikipedia.org/wiki/Data_access_object]DAO[/url]:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。下面的清单4是通过INI配置Shiro使用LDAP目录作为应用Realm的示例。
清单4. Realm配置示例片段:连接存储用户数据的LDAP
[url=http://shiro.apache.org/web.html]Apache Shiro Web文档[/url]可以了解更多内容。
[h2]Web会话管理[/h2]
最后值得一提的是Shiro在Web环境中对会话的支持。
[h3]缺省Http会话[/h3]
对于Web应用,Shiro缺省将使用我们习以为常的Servlet容器会话作为其会话基础设施。即,当你调用subject.getSession()和subject.getSession(boolean)方法时,Shiro会返回Servlet容器的HttpSession实例支持的Session实例。这种方式的曼妙之处在于调用subject.getSession()的业务层代码会跟一个Shiro Session实例交互 - 还没有“认识”到它正跟一个基于Web的HttpSession打交道。这在维护架构层之间的清晰隔离时,是一件非常好的事情。
[h3]Web层中Shiro的原生会话[/h3]
如果你由于需要Shiro的企业级会话特性(如容器无关的集群)而打开了Shiro的原生会话管理,你当然希望HttpServletRequest.getSession()和HttpSession API能和“原生”会话协作,而非Servlet容器会话。如果你不得不重构所有使用HttpServletRequest和HttpSession API的代码,使用Shiro的Session API来替换,这将非常令人沮丧。Shiro当然从来不会期望你这么做。相反,Shiro完整实现了Servlet规范中的Session部分以在Web应用中支持原生会话。这意味着,不管何时你使用相应的HttpServletRequest或HttpSession方法调用,Shiro都会将这些调用委托给内部的原生会话API。结果,你无需修改Web代码,即便是你正在使用Shiro的‘原生'企业会话管理 - 确实是一个非常方便(且必要)的特性。
[h1]附加特性[/h1]
Apache Shiro框架还包含有对保护Java应用非常有用的其他特性,如:
[list]
[*]为维持跨线程的Suject提供了线程和并发支持(支持Executor和ExecutorService);[/*]
[*]为了将执行逻辑作为一种特殊的Subject,支持Callable和Runnable接口;[/*]
[*]为了表现为另一个Subject的身份,支持“Run As”(比如,在管理应用中有用);[/*]
[*]支持测试工具,这样可以很容易的对Shiro的安全代码进行单元测试和集成测试。[/*]
[/list]
[h1]框架局限[/h1]
常识告诉我们,Apache Shiro不是“银弹” - 它不能毫不费力的解决所有安全问题。如下是Shiro还未解决,但是值得知道的:
[list]
[*][b]虚拟机级别的问题[/b]:Apache Shiro当前还未处理虚拟机级别的安全,比如基于访问控制策略,阻止类加载器中装入某个类。然而,Shiro集成现有的JVM安全操作并非白日做梦 - 只是没人给项目贡献这方面的工作。[/*]
[*][b]多阶段认证[/b]:目前,Shiro不支持“多阶段”认证,即用户可能通过一种机制登录,当被要求再次登录时,使用另一种机制登录。这在基于Shiro的应用中已经实现,但是通过应用预先收集所有必需信息再跟Shiro交互。这个功能在Shiro的未来版本中非常有可能得到支持。[/*]
[*][b]Realm写操作[/b]:目前所有Realm实现都支持“读”操作来获取验证和授权数据以执行登录和访问控制。诸如创建用户帐户、组和角色或与用户相关的角色组和权限这类“写”操作还不支持。这是因为支持这些操作的应用数据模型变化太大,很难为所有的Shiro用户强制定义“写”API。[/*]
[/list]
[h1]未来的特性[/h1]
Apache Shiro社区每天都在壮大,借此,Shiro的特性亦是如此。在即将发布的版本中,你可能会看到:
[list]
[*]更干净的Web过滤机制,无需子类化就可支持更多的插件式过滤器。[/*]
[*]更多可插拔的缺省Realm实现,优先采用组合而非继承。你可以插入查找认证和授权数据的组件,无需实现为Shiro Realm的子类;[/*]
[*]强健的[url=http://openid.net/]OpenID[/url]和[url=http://oauth.net/]OAuth[/url](可能是混合)客户端支持;[/*]
[*]支持Captcha;[/*]
[*]针对纯无状态应用的配置简化(如,许多REST环境);[/*]
[*]通过请求/响应协议进行多阶段认证;[/*]
[*]通过AuthorizationRequest进行粗粒度的授权;[/*]
[*]针对安全断言查询的[url=http://www.antlr.org/]ANTLR[/url]语法(比如,(‘role(admin) && (guest || !group(developer))')[/*]
[/list]
[h1]总结[/h1]
Apache Shiro是一个功能齐全、健壮、通用的Java安全框架,你可以用其为你的应用护航。通过简化应用安全的四个领域,即认证、授权、会话管理和加密,在真实应用中,应用安全能更容易被理解和实现。Shiro的简单架构和兼容JavaBean使其几乎能够在任何环境下配置和使用。附加的Web支持和辅助功能,比如多线程和测试支持,让这个框架为应用安全提供了“一站式”服务。Apache Shiro开发团队将继续前进,精炼代码库和支持社区。随着持续被开源和商业应用采纳,可以预期Shiro会继续发展壮大。
[h1]资源[/h1]
[list]
[*]Apache Shiro的[url=http://shiro.apache.org/]主页[/url]。[/*]
[*]Shiro的[url=http://shiro.apache.org/download.html]下载页面[/url],包含面向Maven和Ant+Ivy用户的额外信息。[/*]
[*]Apache Shiro的[url=http://shiro.apache.org/documentation.html]文档页面[/url],包含指南和参考手册。[/*]
[*][url=http://shiro.apache.org/2011/01/06/apache-shiro-video-and-slide-from-sf-jug-presentation.html]Apache Shiro演讲视频和幻灯[/url],项目的PMC主席Les Hazlewood提供。[/*]
[*]其他关于Apache Shiro的[url=http://shiro.apache.org/articles.html]文章和幻灯[/url][/*]
[*]Apache Shiro的[url=http://shiro.apache.org/mailing-lists.html]邮件列表[/url]和[url=http://shiro.apache.org/forums.html]论坛[/url]。[/*]
[*][url=http://www.katasoft.com/]Katasoft[/url] - 提供Apache Shiro专业支持和应用安全产品的公司。[/*]
[/list]
[b]关于作者[/b]
Les Hazlewood是Apache Shiro PMC主席以及[url=http://www.katasoft.com/]Katasoft[/url]的CTO和合伙创办人,该公司是专注于应用安全产品以及提供Apache Shiro专业支持的创业公司。作为专业Java开发人员及企业架构师,以及之前Bloomberg,Delta Airlines和JBoss的高级角色,Les拥有10年的的经验。Les积极从事开源开发已有9年时间,提交或做出贡献的项目有Spring框架、Hibernate、JBoss,OpenSpaces,当然还有JSecurity,Apache Shiro的前身。Les目前居住在加州的圣马特奥,不编程时,他会练习剑道和学习日语。
[b]查看英文原文:[/b][url=http://www.infoq.com/articles/apache-shiro] Application Security With Apache Shiro[/url]
感谢[url=http://www.infoq.com/cn/bycategory.action?authorName=%E8%83%A1%E9%94%AE]胡键[/url]对本文的审校。