Apache Shiro™ 是一个功用强壮且易于运用的 Java 安全结构,用于履行身份验证、授权、加密和会话办理。凭借 Shiro 易于了解的 API,您能够快速轻松地保护任何运用程序 – 从最小的移动运用程序到最大的 Web 和企业运用程序。

一、什么是 Apache Shiro?

Apache Shiro(发音为“shee-roh”,日语中“城堡”的意思)是一个功用强壮且易于运用的 Java 安全结构,它履行身份验证、授权、加密和会话办理,可用于保护任何运用程序的安全 -从命令行运用程序、移动运用程序到最大的 Web 和企业运用程序。

Shiro 供给了运用程序安全 API 来履行以下方面(我喜欢将它们称为运用程序安全性的 4 个基石):

  • Authentication – 供给用户的身份认证,一般被称为用户登录。
  • Authorization – 拜访操控
  • Cryptography – 保护或躲藏数据免遭窥视
  • Session Management – 每个用户的时间敏感状况

Shiro 还支撑一些辅佐功用,例如 Web 运用程序安全性、单元测验和多线程支撑,但这些功用的存在是为了强化上述四个首要问题。

二、为什么创立Apache Shiro?

关于一个结构来说,要真实证明它的存在,并因而成为你运用它的理由,它应该满意其他替代计划无法满意的需求。为了了解这一点,咱们需求看看 Shiro 的历史以及它创立时的替代计划。

在 2008 年参加 Apache 软件基金会之前,Shiro 现已有 5 岁了,之前称为 JSecurity 项目,该项目于 2003 年头发动。2003 年,Java 运用程序开发人员没有太多通用的安全替代计划 – 咱们简直只能运用 Java 身份验证和授权服务,也称为 JAAS。JAAS 有许多缺点——虽然它的身份验证功用还能够接受,但授权方面却很迟钝,运用起来令人懊丧。此外,JAAS 与虚拟机等级的安全问题密切相关,例如,确认是否应答应在 JVM 中加载类。作为一名运用程序开发人员,我更关怀运用程序终究用户能够做什么,而不是我的代码在 JVM 中能够做什么。其时游戏中唯一的会话挑选是 HttpSession(需求 Web 容器)和 EJB 2.1 Stateful Session Beans(需求 EJB 容器)。

由于我其时运用的运用程序,我还需求拜访一个洁净的、与容器无关的会话机制。我需求一些能够与容器别离的东西,能够在我挑选的任何环境中运用。

终究是暗码学问题。有时咱们都需求保证数据安全,但 Java 加密架构很难了解,除非你是加密专家。该 API 充满了查看反常,运用起来很费事。我期望有一个更洁净、开箱即用的处理计划,能够依据需求轻松加密和解密数据。

因而,看看 2003 年头的安全形势,您很快就会意识到没有任何东西能够在一个单一的、有凝聚力的结构中满意一切这些要求。因而,JSecurity 以及后来的 Apache Shiro 诞生了。

三、为什么今天要运用Apache Shiro?

自 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 等商业公司也会供给专业支撑和服务。

四、谁在运用Shiro?

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 从根本上表现了其主题概念中的这种思想办法。

    “主题”一词是一个安全术语,根本上意味着“当时正在履行的用户”。它只是不被称为“用户”,由于“用户”一词一般与人类相关联。在安全范畴,术语“主题”能够指人类,也能够指第 3 方进程、看护程序帐户或任何类似的东西。它只是意味着“当时正在与软件交互的事物”。不过,关于大多数意图和意图,您能够将其视为 Shiro 的“用户”概念。您能够轻松地在代码中的任何方位获取 Shiro 主题,如下面的清单 1 所示。

    一旦您获取了主题,您就能够当即拜访当时用户想要运用 Shiro 履行的 90% 的操作,例如登录、注销、拜访其会话、履行授权查看等等 – 稍后会详细介绍。这儿的关键点是 Shiro 的 API 很大程度上是直观的,由于它反映了开发人员思考“每个用户”安全操控的天然倾向。在代码中的任何方位拜访主题也很简略,然后答应安全操作在需求的任何地方进行。

    清单1:获取主题

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

    主题的“幕后”对应者是 SecurityManager。虽然主题代表当时用户的安全操作,但安全办理器办理一切用户的安全操作。它是 Shiro 架构的中心,充当一种“伞”方针,引用许多形成方针图的内部嵌套安全组件。但是,一旦装备了 SecurityManager 及其内部方针图,一般就不再管它了,运用程序开发人员简直将一切时间都花在了主题 API 上。

    那么怎么设置SecurityManager呢?嗯,这取决于你的运用环境。例如,Web 运用程序一般会在 web.xml 中指定 Shiro Servlet Filter,这将设置 SecurityManager 实例。假如您运行的是独立运用程序,则需求以其他办法装备它。但有许多装备选项。

    每个运用程序简直总是有一个 SecurityManager 实例。它本质上是一个运用程序单例(虽然它不需求是静态单例)。与 Shiro 中的简直一切内容相同,默许的 SecurityManager 完结是 POJO,而且能够运用任何 POJO 兼容的装备机制进行装备 – 普通 Java 代码、Spring XML、YAML、.properties 和 .ini 文件等。根本上,任何能够实例化类并调用 JavaBeans 兼容办法的东西都能够运用。

    为此,Shiro 经过依据文本的 INI 装备供给了默许的“共同点”处理计划。INI 易于阅览、运用简略,而且需求很少的依靠项。您还将看到,经过对方针图导航的简略了解,能够有用地运用 INI 来装备简略的方针图,例如 SecurityManager。请注意,Shiro 还支撑 Spring XML 装备和其他替代计划,但咱们将在这儿介绍 INI。依据 INI 装备 Shiro 的最简略示例如下面的清单 2 中的示例所示。

    清单2:运用 INI 装备 Shiro

    [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
    

    在清单 2 中,咱们看到了将用于装备 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 的文档。

    清单3:加载shiro.ini装备文件

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.util.Factory;
    // 加载INI装备
    Factory<SecurityManager> factory =
    new IniSecurityManagerFactory("classpath:shiro.ini");
    // 创立SecurityManager
    SecurityManager securityManager = factory.getInstance();
    // 使其易于拜访
    SecurityUtils.setSecurityManager(securityManager);
    

    在清单 3 中,咱们在这个简略示例中看到了一个三步进程:

    1. 加载将装备 SecurityManager 及其组成组件的 INI 装备。
    2. 依据装备创立 SecurityManager 实例(运用代表工厂办法规划办法的 Shiro 工厂概念)。
    3. 使 SecurityManager 单例可供运用程序拜访。在这个简略的示例中,咱们将其设置为 VM 静态单例,但这一般是不用要的 – 您的运用程序装备机制能够确认您是否需求运用静态内存。
  • Realms

    Shiro 中的第三个也是终究一个中心概念是Realm。Realm 充当 Shiro 和运用程序安全数据之间的“桥梁”或“衔接器”。也便是说,当实践与安全相关数据(例如用户帐户)进行交互以履行身份验证(登录)和授权(拜访操控)时,Shiro 从为运用程序装备的一个或多个范畴中查找其中的许多内容。

    从这个意义上说,Realm 本质上是一个特定于安全性的 DAO:它封装了数据源的衔接详细信息,并使相关数据依据需求可供 Shiro 运用。装备 Shiro 时,您必须至少指定一个用于身份验证和/或授权的 Realm。能够装备多个 Realm,但至少需求一个。

    Shiro 供给开箱即用的 Realms 来衔接到许多安全数据源(也称为目录),例如 LDAP、联系数据库 (JDBC)、文本装备源(例如 INI 和特点文件)等等。假如默许 Realm 不能满意您的需求,您能够刺进自己的 Realm 完结来表明自界说数据源。下面的清单 4 是装备 Shiro(经过 INI)以运用 LDAP 目录作为运用程序的范畴之一的示例。

    清单4:衔接到 LDAP 用户数据存储的范畴装备片段示例

    [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

身份验证是验证用户身份的进程。也便是说,当用户运用运用程序进行身份验证时,他们就证明自己确实是他们所说的人。这有时也称为“登录”。这一般是一个三步进程。

  1. 搜集用户的身份信息(称为主体)和支撑身份证明(称为凭证)。
  2. 将主体和凭证提交到体系。
  3. 假如提交的凭证与体系对该用户身份(主体)的期望相匹配,则该用户被视为现已过身份验证。假如不匹配,则用户不会被视为现已过身份验证。

每个人都了解的此进程的一个常见示例是用户名/暗码组合。当大多数用户登录软件运用程序时,他们一般会供给用户名(主体)和支撑暗码(凭证)。假如体系中存储的暗码(或其表明办法)与用户指定的内容匹配,则以为他们现已过身份验证。

Shiro 以简略直观的办法支撑相同的作业流程。正如咱们所说,Shiro 有一个以主题为中心的 API – 简直您在运行时运用 Shiro 做的一切作业都是经过与当时履行的主题交互来完结的。因而,要登录主题,您只需调用其登录办法,传递代表提交的主体和凭证(在本例中为用户名和暗码)的 AuthenticationToken 实例。下面的清单 5 显现了这个示例。

清单5:主题登录

//1. 获取提交的主体和凭证:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
//2. 获取当时主题:
Subject currentUser = SecurityUtils.getSubject();
//3. 登录:
currentUser.login(token);

正如您所看到的,Shiro 的 API 很简略反映常见的作业流程。您将继续将这种简略性视为一切主题操作的主题。当调用登录办法时,安全办理器将接收身份验证令牌并将其分派到一个或多个装备的范畴,以答应每个范畴依据需求履行身份验证查看。每个范畴都能够依据需求对提交的 AuthenticationToken 做出反响。但是假如登录测验失利会发生什么?假如用户指定了过错的暗码怎么办?您能够经过对 Shiro 的运行时 AuthenticationException 做出反响来处理毛病,如清单 6 所示。

清单6:处理登录失利

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

您能够挑选捕获 AuthenticationException 子类之一并做出详细反响,或许一般性地处理任何 AuthenticationException(例如,向用户显现通用的“用户名或暗码不正确”音讯)。您能够依据您的运用要求进行挑选。

主题成功登录后,他们被视为现已过身份验证,一般您答应他们运用您的运用程序。但只是由于用户证明了他们的身份并不意味着他们能够在您的运用程序中做任何他们想做的作业。这就引出了下一个问题:“我怎么操控用户能够做什么或不能够做什么?”决定答运用户做什么称为授权。接下来咱们将介绍 Shiro 怎么启用授权。

七、Authorization

授权本质上是拜访操控——操控用户能够在运用程序中拜访哪些内容,例如资源、网页等。大多数用户经过运用人物和权限等概念来履行拜访操控。也便是说,一般答运用户履行或不履行某些操作,详细取决于分配给他们的人物和/或权限。然后,您的运用程序能够依据对这些人物和权限的查看来操控公开哪些功用。正如您所期望的,Subject API 答应您十分轻松地履行人物和权限查看。例如,清单 7 中的代码片段显现了怎么查看主题是否已被分配特定人物。

清单7:人物查看

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

如您所见,您的运用程序能够依据拜访操控查看启用或禁用功用。

权限查看是履行授权的另一种办法。如上例所示查看人物存在一个重大缺陷:您无法在运行时增加或删去人物。您的代码是运用人物称号进行硬编码的,因而假如您更改了人物称号和/或装备,您的代码将会被损坏!假如您需求能够在运行时更改人物的意义,或许依据需求增加或删去人物,则必须依靠其他东西。

为此,Shiro 支撑其权限概念。权限是功用的原始声明,例如“打开一扇门”、“创立博客条目”、“删去“jsmith”用户”等。经过让权限反映运用程序的原始功用,您只需在更改运用程序的功用时更改权限查看。反过来,您能够在运行时依据需求向人物或用户分配权限。作为示例,如下面的清单 8 所示,咱们能够重写您之前的人物查看并改为运用权限查看。

清单8:权限查看

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

这样,任何分配了“user:create”权限的人物或用户都能够单击“创立用户”按钮,而且这些人物和分配乃至能够在运行时更改,然后为您供给十分灵敏的安全模型。

“user:create”字符串是遵从某些解析约好的权限字符串的示例。Shiro 经过其 WildcardPermission 开箱即用地支撑此约好。虽然超出了本文的介绍规模,但您将看到 WildcardPermission 在创立安全策略时十分灵敏,乃至支撑实例级拜访操控等功用。

清单9:实例级权限查看

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

此示例表明,假如需求,您能够操控对各个资源的拜访,乃至能够操控到十分细粒度的实例等级。假如您乐意,您乃至能够创造自己的权限语法。有关更多信息,请参阅 Shiro 权限文档。终究,就像身份验证相同,上述调用终究会抵达 SecurityManager,SecurityManager 将咨询一个或多个范畴来做出拜访操控决策。这答应范畴依据需求响应身份验证和授权操作。

这便是 Shiro 授权功用的扼要概述。虽然大多数安全结构仅限于身份验证和授权,但 Shiro 供给了更多功用。接下来咱们将讨论 Shiro 的高级会话办理功用。

八、Session Management

Apache Shiro供给了世界上绝无仅有的安全结构:一个可用于任何运用程序和任何架构层的共同的会话API。也便是说,Shiro 为任何运用程序启用了会话编程范例 – 从小型看护程序独立运用程序到最大的集群 Web 运用程序。这意味着期望运用会话的运用程序开发人员不再被逼运用 Servlet 或 EJB 容器(假如他们不需求)。或许,假如运用这些容器,开发人员现在能够挑选在任何层中运用统一且共同的会话 API,而不是 servlet 或 EJB 特定的机制。

但或许 Shiro 会话最重要的优点之一是它们独立于容器。这具有奇妙但极其强壮的意义。例如,让咱们考虑会话集群。有多少种特定于容器的办法来集群会话以完结容错和毛病转移? Tomcat 的做法与 Jetty 不同,Jetty 的做法又与 Websphere 等不同。但经过 Shiro 会话,您能够取得独立于容器的集群处理计划。 Shiro 的架构答应可刺进的会话数据存储,例如企业缓存、联系数据库、NoSQL 体系等。这意味着您只需装备一次会话集群,不管您的布置环境怎么(Tomcat、Jetty、JEE Server 或独立运用程序),它都会以相同的办法作业。无需依据您布置运用程序的办法重新装备您的运用程序。Shiro 会话的另一个优点是,假如需求,能够跨客户端技能共享会话数据。例如,假如需求,Swing 桌面客户端能够参与同一个 Web 运用程序会话 – 假如终究用户一同运用两者,这很有用。那么怎么在任何环境中拜访主题的会话呢?有两种主题办法,如下例所示。

清单10:主题会话

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

正如您所看到的,这些办法在概念上与 HttpServletRequest API 相同。第一个办法将回来主题的现有会话,或许假如还没有会话,它将创立一个新会话并回来它。第二种办法接受一个布尔参数,用于确认是否创立新会话(假如尚不存在)。一旦取得了主题的会话,就能够像运用 HttpSession 相同运用它。 Shiro 团队以为 HttpSession API 关于 Java 开发人员来说是最舒服的,因而咱们保留了它的大部分感觉。当然,最大的区别是您能够在任何运用程序中运用 Shiro Sessions,而不只是是 Web 运用程序。清单 11 显现了这种了解性。

清单11:会话办法

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

九、Cryptography

暗码学是躲藏或混淆数据的进程,使窥视者无法了解它。 Shiro 在暗码学方面的方针是简化并供给 JDK 的暗码学支撑。

值得注意的是,暗码学一般并不特定于主题,因而它是 Shiro API 中不特定于主题的一个范畴。您能够在任何地方运用 Shiro 的加密支撑,即便没有运用主题。Shiro 真实关注加密支撑的两个范畴是加密哈希(也称为音讯摘要)和加密暗码。让咱们更详细地看看这两个。

  • 哈希

    假如您运用过 JDK 的 MessageDigest 类,您很快就会意识到它运用起来有点费事。它有一个笨拙的依据静态办法工厂的 API,而不是面向方针的 API,而且您被逼捕获或许永久不需求捕获的已查看反常。假如您需求对音讯摘要输出进行十六进制编码或 Base64 编码,则只能靠您自己了——两者都没有规范的 JDK 支撑。 Shiro 经过洁净直观的哈希 API 处理了这些问题。

    例如,让咱们考虑一下相对常见的情况,即对文件进行 MD5 哈希处理并确认该哈希值的十六进制值。这称为“校验和”,在供给文件下载时经常运用 – 用户能够对下载的文件履行自己的 MD5 哈希,并断言其校验和与下载网站上的校验和匹配。假如它们匹配,用户就能够充分假定文件在传输进程中没有被篡改。

    以下是您在没有 Shiro 的情况下测验履行此操作的办法:

    1. 将文件转化为字节数组。 JDK 中没有任何东西能够协助处理这个问题,因而您需求创立一个辅佐办法来打开 FileInputStream、运用字节缓冲区并抛出恰当的 IOException 等。
    2. 运用 MessageDigest 类对字节数组进行哈希处理,处理恰当的反常,如下面的清单 12 所示。
    3. 将哈希字节数组编码为十六进制字符。 JDK 中也没有任何东西能够协助处理这个问题,因而您需求创立另一个辅佐办法,而且或许在完结中运用按位运算和位移。

    清单12:JDK 的 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 在多大程度上简化了散列和编码,然后让您在此进程中坚持沉着。

  • 暗码

    暗码是能够运用密钥可逆地转化数据的加密算法。咱们运用它们来保证数据安全,特别是在传输或存储数据时,此刻数据特别简略被窥视。

    假如您从前运用过 JDK Cryptography API,特别是 javax.crypto.Cipher 类,您就会知道它或许是一头难以驯服的极其复杂的野兽。关于初学者来说,每个或许的 Cipher 装备始终由 javax.crypto.Cipher 的实例表明。需求进行公钥/私钥加密吗?你运用暗码。需求运用分组暗码进行流操作?你运用暗码。需求创立 AES 256 位暗码来保护数据?你运用暗码。你明白了。

    以及怎么创立您需求的 Cipher 实例?您创立一个复杂的、不直观的、以符号分隔的暗码选项字符串,称为“转化字符串”,并将该字符串传递给 Cipher.getInstance 静态工厂办法。运用这种暗码选项字符串办法,没有类型安全性来保证您运用有用的选项。这也隐含地意味着没有 JavaDoc 来协助您了解相关选项。即便您知道装备是正确的,您还需求处理已查看的反常,以防您的字符串格局不正确。正如您所看到的,运用 JDK Ciphers 是一项适当繁琐的任务。这些技能很久以前就从前是 Java API 的规范,但时代现已改变,咱们需求一种更简略的办法。

    Shiro 企图经过引入其 CipherService API 来简化加密暗码的整个概念。 CipherService 是大多数开发人员在保护数据时想要的:一种简略、无状况、线程安全的 API,能够在一个办法调用中完整地加密或解密数据。您所需求做的便是供给您的密钥,然后您能够依据需求进行加密或解密。例如,能够运用 256 位 AES 加密,如下面的清单 13 所示。

    清单13:Apache Shiro 加密 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 Filter。清单 14 显现了此代码。

清单14:web.xml 中的 ShiroFilter

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>
        org.apache.shiro.web.servlet.IniShiroFilter
    </filter-class>
    <!-- no init-param means load the INI config
        from classpath:shiro.ini --> 
</filter>
<filter-mapping>
     <filter-name>ShiroFilter</filter-name>
     <url-pattern>/*</url-pattern>
</filter-mapping>

此过滤器能够读取上述 shiro.ini 装备,因而不管布置环境怎么,您都能够取得共同的装备体验。装备完结后,Shiro Filter 将过滤每个恳求,并保证恳求特定的主题在恳求期间可拜访。由于它会过滤每个恳求,因而您能够履行特定于安全性的逻辑,以保证只答应满意特定条件的恳求经过。

  • URL特定的过滤器链

    Shiro 经过其创新的 URL 过滤器链接功用支撑特定于安全的过滤规矩。它答应您为任何匹配的 URL 办法指定临时过滤器链。这意味着您在运用 Shiro 的过滤机制履行安全规矩(或规矩组合)时具有很大的灵敏性 – 比单独在 web.xml 中界说过滤器要灵敏得多。清单 15 显现了 Shiro INI 中的装备片段。

    清单15:特定于途径的过滤器链

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

    正如您所看到的,有一个 [urls] INI 部分可供 Web 运用程序运用。关于每一行,等号左边的值表明上下文相关的 Web 运用程序途径。右侧的值界说了一个过滤器链 – 一个有序的、以逗号分隔的 Servlet 过滤器列表,要针对给定途径履行。每个过滤器都是普通的 Servlet 过滤器,但您在上面看到的过滤器称号(anon、user、perms、authc)是 Shiro 开箱即用供给的特殊安全相关过滤器。您能够混合搭配这些安全过滤器来创立十分自界说的安全体验。您还能够指定任何其他现有的 Servlet 过滤器。

    与运用 web.xml 比较,这要好得多,在 web.xml 中界说一个过滤器块,然后界说一个单独的断开衔接的过滤器办法块?运用 Shiro 的办法,能够更轻松地准确查看针对给定匹配途径履行的过滤器链。假如您乐意,您能够在 web.xml 中仅界说 Shiro 过滤器,并在 shiro.ini 中界说一切其他过滤器和过滤器链,以取得比 web.xml 更简洁且易于了解的过滤器链界说机制。即便您没有运用 Shiro 的任何安全功用,仅这一点小小的便当就足以让 Shiro 值得运用。

  • JSP标签库

    Shiro 还供给了一个 JSP 标签库,答应您依据当时主题的状况操控 JSP 页面的输出。一个常见的比如是在用户登录后显现“Hello ”文本。但假如他们是匿名的,您或许想显现其他内容,例如“您好!今天就注册!”反而。清单 16 显现了怎么运用 Shiro 的 JSP 符号来支撑这一点。

    清单16:JSP 标签库示例

    <%@ taglib prefix="shiro"
        uri="http://shiro.apache.org/tags" %>
    ...
    <p>Hello
    <shiro:user>
        <!-- shiro:principal prints out the Subject’s main
            principal - in this case, a username: -->
        <shiro:principal/>!
    </shiro:user>
    <shiro:guest>
        <!-- not logged in - considered a guest. Show
            the register link: -->
        ! <a href=”register.jsp”>Register today!</a>
    </shiro:guest>
    </p>
    

    还有其他标签,答应您依据他们具有(或不具有)的人物、分配(或未分配)哪些权限以及他们是否经过身份验证、是否经过“记住我”服务记住或经过“记住我”服务来包含输出。匿名客人。

    Shiro 支撑许多其他特定于 Web 的功用,例如简略的“记住我”服务、REST 和 BASIC 身份验证,当然还有透明的 HttpSession 支撑(假如您想运用 Shiro 的本机企业会话)。请参阅 Apache Shiro Web 文档了解更多信息。

  • 网络会话办理

    终究,有趣的是 Shiro 对 Web 环境中会话的支撑。

    • 默许 Http 会话

      关于 Web 运用程序,Shiro 默许其会话基础结构运用咱们都习气的现有 Servlet 容器会话。也便是说,当您调用办法 subject.getSession() 和 subject.getSession(boolean) 时,Shiro 将回来由 Servlet 容器的 HttpSession 实例支撑的 Session 实例。这种办法的优点在于,调用 subject.getSession() 的业务层代码与 Shiro Session 实例进行交互 – 它不“知道”它正在运用依据 Web 的 HttpSession 方针。当坚持跨架构层的清晰别离时,这是一件十分好的作业。

    • Shiro 在 Web 层的本机会话

      假如您在 Web 运用程序中启用了 Shiro 的本机会话办理,由于您需求 Shiro 的企业会话功用(例如独立于容器的集群),那么您当然期望 HttpServletRequest.getSession() 和 HttpSession API 能够与“本机”会话一同作业,而且不是 servlet 容器会话。假如您必须重构任何运用 HttpServletRequest 和 HttpSession API 的代码来替代运用 Shiro 的 Session API,那将是十分令人懊丧的。白当然不会想到你会这么做。相反,Shiro 彻底完结了 Servlet 规范的 Session 部分,以支撑 Web 运用程序中的本机会话。这意味着每当您调用相应的 HttpServletRequest 或 HttpSession 办法调用时,Shiro 都会将这些调用托付给其内部本机 Session API。终究结果是,即便您运用 Shiro 的“本机”企业会话办理,您也不用更改 Web 代码 – 这确实是一个十分方便(且必要)的功用。

十一、附加功用

Apache Shiro 结构中还有其他功用关于保护 Java 运用程序很有用,例如:

  • 用于跨线程保护主题的线程和并发支撑(Executor 和 ExecutorService 支撑)
  • Callable 和 Runnable 支撑作为特定主题履行逻辑
  • “运行办法”支撑假定另一个主体的身份(例如在办理运用程序中有用)
  • 测验工具支撑,使得在单元测验和集成测验中对 Shiro 安全代码进行全面测验变得十分简略

十二、结构约束

虽然咱们期望如此,Apache Shiro 并不是“灵丹妙药”——它无法轻松处理一切安全问题。 Shiro 没有提及的一些作业或许值得了解:

  • 虚拟机等级的问题:Apache Shiro 现在不处理虚拟机等级的安全性,例如依据拜访操控策略阻止某些类加载到类加载器中的能力。但是,Shiro 能够与现有的 JVM 安全操作集成并不是不行幻想的——只是没有人为该项目贡献这样的作业。
  • 多阶段身份验证:Shiro 现在本身不支撑“多阶段”身份验证,即用户或许经过一种机制登录,然后被要求运用不同的机制再次登录。这现已在依据 Shiro 的运用程序中完结,但是运用程序预先搜集一切必需的信息,然后与 Shiro 交互。未来的 Shiro 版别很或许会支撑此功用。
  • Realm 写入操作:现在一切 Realm 完结都支撑“读取”操作,用于获取身份验证和授权数据以履行登录和拜访操控。不支撑“写入”操作,例如创立用户帐户、组和人物,或将用户与人物组和权限关联。这是由于支撑这些操作的数据模型在不同的运用程序中差异很大,而且很难对一切 Shiro 用户强制履行“写入”API。

十三、行将推出的功用

Apache Shiro 社区每天都在不断发展,Shiro 的功用也随之不断发展。在行将推出的版别中,您或许会看到:

  • 更洁净的 Web 过滤器机制,答应更多可刺进过滤支撑,而无需子类化。
  • 更多可刺进的默许 Realm 完结有利于组合而不是继承。您将能够刺进查找身份验证和授权数据的组件,而不需求子类化 Shiro Realm 完结
  • 强壮的 OpenID 和 OAuth(或许还有混合)客户端支撑
  • 验证码支撑
  • 更轻松地装备 100% 无状况运用程序(例如许多 REST 环境)。
  • 经过恳求/响应协议进行多阶段身份验证。
  • 经过 AuthorizationRequest 进行粗粒度授权。
  • 用于安全断言查询的 ANTLR 语法(例如 (‘role(admin) && (guest || !group(developer))’)

十四、总结

Apache Shiro 是一个功用齐全、强壮且通用的 Java 安全结构,可用于保护您的运用程序。经过简化运用程序安全的四个范畴,即身份验证、授权、会话办理和暗码学,运用程序安全性在实践运用程序中更简略了解和完结。 Shiro 的简略架构和 JavaBeans 兼容性使其简直能够在任何环境中装备和运用。额外的 Web 支撑和辅佐功用(如多线程和测验支撑)完善了结构,为您的运用程序安全供给了“一站式服务”。 Apache Shiro 的开发团队不断前进,完善代码库并支撑社区。随着开源和商业运用的继续发展,Shiro 有望变得愈加强壮。

十五、资源

  • Apache Shiro的主页
  • Shiro 的下载页面,包含 Maven 和 Ant+Ivy 用户的附加信息。
  • Apache Shiro 的文档页面,包含指南和参考手册
  • Apache Shiro演示视频和幻灯片,由该项意图 PMC 主席 Les Hazlewood 演示。
  • 其他 Apache Shiro文章和演示文稿
  • Apache Shiro邮件列表和论坛。