Shiro 诉 SpringSecurity

我目前正在评估基于 Java 的安全框架,我是一个 Spring 3.0用户,所以似乎 SpringSecurity 是正确的选择,但 Spring 安全似乎受到过度复杂性的影响,当然它似乎并没有使安全更容易实现,Shiro 似乎更连贯,更容易理解。我正在寻找这两个框架之间的利弊列表。

44194 次浏览

我没有使用 Shiro 的经验,而且我“部分”同意您关于 Spring 安全性的说法。在 Spring Security 3.x 之前,设置 Spring Security (或 Acegi)非常痛苦。一个简单的基于角色的配置将需要至少140行隐蔽的 XML 配置... ... 我知道这一点,因为我实际上自己计算了这些行。这是你设置了一次,你祈祷它将永远工作,而不会再次触及配置,因为你可以保证你已经忘记了所有的配置意味着什么。:)

通过 Spring Security 3.x,它得到了极大的改进。它引入了 security命名空间,大幅度地将配置从140行缩短到30行。下面是我的一个项目的 Spring Security 3.x 示例:-

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">


<security:http auto-config="true">
<security:form-login login-page="/index.do" authentication-failure-url="/index.do?login_error=1" default-target-url="/index.do"
always-use-default-target="true" />
<security:logout logout-success-url="/index.do" />
<security:intercept-url pattern="/secure/**" access="ROLE_ADMIN,ROLE_USER" />
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</security:http>


<bean id="customAuthenticationProvider" class="my.project.CustomAuthenticationProviderImpl">
...
</bean>


<security:authentication-manager>
<security:authentication-provider ref="customAuthenticationProvider" />
</security:authentication-manager>


</beans>

Spring Security 3.x 的美妙之处在于它是极其可配置的,这导致了一个主要缺点: 太复杂以至于无法理解。这些文档也不容易阅读,因为我对 Spring Security 使用的一些术语只是部分地熟悉。但是,如果需要创建自定义配置或控制安全性的粒度,则可以使用这些选项。或者,您可以坚持使用上面的 < 30行来执行基于角色的安全检查。

我真正喜欢 Spring Security 的地方在于,它一旦建立起来,安全性就会无缝地集成到项目中。这就好像实际的项目代码不知道安全性的存在... ... 这是好事,因为它允许我在将来轻松地分离或升级安全性组件(例如: 将数据库认证更改为 LDAP/CAS 认证)。

我也同意 Spring Security (对我来说)感觉太复杂了。当然,他们已经做了一些事情来降低复杂性,比如创建定制的 XML 名称空间来减少 XML 配置的数量,但是对我来说,这些并没有解决 Spring Security 的 天啊个人基本问题: 它的名称和概念对我来说通常是混乱的。很难只是“得到它”。

一旦你开始使用四郎,你只是’得到它’。在安全领域难以理解的东西,也就更容易理解了。在 JDK 中难以使用的东西(比如 Ciphers)被简化到了一个不仅可以忍受,而且使用起来非常愉快的级别。

例如,如何散列 + 加盐一个密码和 base64编码它在 Java 或 Spring 安全?两者都不如四郎的解决方案简单直观:

ByteSource salt = new SecureRandomNumberGenerator().nextBytes();
new Sha512Hash(password, salt).toBase64();

不需要 commons-codec 或者其他东西,只需要 Shiro 罐。

现在,关于 Spring 环境,大多数 Shiro 开发人员使用 Spring 作为他们的主要应用程序环境。这意味着 Shiro 的 Spring 集成是一流的,并且所有的工作都非常好。您可以放心,如果您正在编写一个 Spring 应用程序,那么您将获得全面的安全体验。

例如,请考虑本线程另一篇文章中的 SpringXML 配置示例。以下是你在希罗会做的(本质上)同样的事情:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd>


<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/home.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<property name="filterChainDefinitions">
<value>
/secure/** = authc
/** = anon
</value>
</property>
</bean>


<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>


<bean id="myRealm" class="...">
...
</bean>

虽然比另一个 Spring 示例稍微冗长一些,但是它更容易阅读 IMO。

您还会发现,使用 Shiro 的过滤器链定义可能是定义通用过滤器链和基于 Web 的安全规则的最简单方法!比在 web.xml 中定义它们要好得多。

最后,Shiro 还提供了极端的“可插拔性”。您将看到,您可以配置和/或替换几乎任何东西,因为 Shiro 的 POJO/注入友好架构。Shiro 将几乎所有内容都默认为理智的默认值,您只能覆盖或配置您需要的内容。

在一天结束的时候,我认为选择这两者中的任何一个更多的是关于你的思维模式——这两者中的哪一个对你来说更有意义和更直观?对于一些人来说,它将是 Shiro,对于其他人来说,它将是 Spring Security。Shiro 在 Spring 环境中工作得很好,所以我认为应该根据这两个环境中你更喜欢哪一个,哪一个对你来说最有意义。

更多关于 Shiro 的 Spring 集成: http://shiro.apache.org/spring.html

我已经使用 Spring Security (版本3.1)几个月了,并且对它非常满意。它真的很强大,并有一些非常好的功能,特别是在实现了一切后,因为我以前所做的!不过,就像我在某个地方读到的那样,你在应用程序开发之初设置了一些东西,然后祈祷它能一直工作到最后,因为如果你不得不去修复它,你可能已经忘记了大部分需要参数化的东西。

但是后来出现了一个新项目,带有更复杂的安全需求。简而言之,我们必须在两个相关的 Web 应用程序之间实现某种自定义 SSO。

我确切地知道我想要在 HTTP 逻辑、 cookie、会话 ID 和其他东西方面实现什么,以及应该以什么顺序发生什么,但是我花了一天的大部分时间与 Spring Security API 作斗争,仍然不能确切地弄清楚我应该实现或覆盖什么类或接口,以及如何在上下文中插入它们。整个 API 给人的感觉非常复杂,有时还有点深奥。虽然该文档对于一般用例甚至一些定制都很好,但是它还不足以满足我的需求。

在阅读了这里和网上其他一些地方的答案后,我得到的印象是 Shiro 会更容易理解和定制我的需求。所以我试了试。

我很高兴我做到了,因为经过一天的工作,我学到了足够多的 API,不仅可以毫无困难地在我的 Spring 网络应用中建立一个基本的认证和授权系统,而且还可以实现我一直在寻找的自定义 SSO 行为。我只需要扩展2到3个类,在我的 Spring 上下文中,整个过程只需要大约25行 XML 配置。

所以总的来说,在易用性和学习曲线方面,Shiro 确实很讨人喜欢,我想我可能会在未来继续使用它,除非我遇到一些缺乏的功能或其他问题(目前为止我还没有遇到)。

两者都很强大,但 Shiro 更容易学习。