分享

Spring security和shiro哪个更强?

 拼命奋斗的自己 2020-07-20

抽象

本文根据自定义类别将Java EE Security与Apache Shiro和Spring Security进行了比较。它针对希望获得一个大致概念的读者,该选择哪种框架来保护其应用程序。因此,本篇文章将不深入。为了提供一些上下文,我们将简要介绍测试环境。然后进行实际比较。自定义类别为文档,易用性,社区支持和差异化功能。结论中总结了我们的发现。

简要概述

Java EE安全性API

Java EE应用程序通常包含多个组件。甲容器保持这些部件。Java EE的安全性模型指定容器必须提供或支持某些安全性功能。您可以通过两种方式实现这些功能:声明式和编程式。

声明性的:开发人员在部署描述符和/或代码中使用注释指定安全要求。关于注释的最酷的事情是,您可以将它们放在类和/或方法上,而不用编写冗长的XML代码。

程序化的:提供基于安全上下文做出与安全相关的决策的能力。如果注释和部署描述符的表达能力不够,“ Java EE教程,第7版”文档建议使用此方法。一个示例是使资源仅在一天的特定时间访问。

两种方法都基于Java身份验证和授权服务(JAAS) API。

Apache ShiroApache Shiro

的两个主要特征(“ shiro” = jap。“ castle”)是简单性和容器独立性。它的核心功能是身份验证,授权,加密和会话管理。

身份验证设计简单而直观。该过程是基于主题的,由开发人员仅使用几个方法调用来执行。丰富的异常层次结构有助于错误诊断。记住,我本身就包含功能。可插拔DAO可以用于实现领域,并且可以将一个主题登录到多个领域,同时保持其统一视图。

授权也是基于主题的。访问权限由主题角色和权限确定。要立即开始实施权限,可以使用Shiro的自制通配符权限语法。为了改善用户体验和性能,支持不同的缓存解决方案。

密码学功能以简单性为中心。Shiro的主要目标是使Java密码学扩展易于使用。由于Shiro的API是接口驱动和基于POJO的,因此可以使用任何JavaBeans兼容格式轻松配置加密组件。

即使对于非基于Web的应用程序,也可以使用Shiro进行会话管理。由于会话对象也是POJO的对象,因此可以将它们持久保存在任何类型的存储中。一些更流行的缓存解决方案也可以在这里使用。

此外,Shiro还提供特定于Web的功能。通过通过web.xml为您的应用程序启用Shiro,您可以保护任何URL,还可以为每个URL指定过滤器链。

Spring Security

与前两个框架一样,Spring Security的功能围绕身份验证和授权。它可以与无Spring的应用程序以及基于Spring的应用程序一起使用。这主要是因为与Apache Shiro一样,Spring Security与容器无关。

Spring Security的创建始于2003年下半年,当时是一个名为“ Spring Acegi Security System”的项目,当时是一个简单的实现,最初并未发布。随着越来越多的Spring社区成员要求提供安全功能,他们获得了上述项目。2004年初,大约有20个人在使用该项目。越来越多的人加入,最终在2004年3月创建了SourceForge项目。2006年5月,Acegi成为Spring的正式子项目,在2007年,它成为Spring Portfolio的一部分,并更名为“ Spring Security”。

测试环境

该框架是一个简单的测试Web的应用程序组成的的REST API和一个index.html(也:登录/注销/的error.html)在开发Eclipse的霓虹灯对Java EE与WildFly 10.1.0.Final作为应用服务器和PostgreSQL 9.6的持久性。

框架的配置尽可能以声明式进行。

比较方式

请注意,这是这三个框架之间的相对比较。

Java EE安全性文档绝对是最基础的文档,因为它不仅说明了如何使用安全性功能,而且还花了一些时间(而且篇幅较长,篇幅较长)来解释基本的应用程序安全性概念。大多数其他框架都遵循文档中列出的安全模型,因此即使您不打算实际使用API,也值得一读,特别是对于初学者。但是,如果您想快速入门,则可能需要寻找更简洁的方法。

Spring Security的文档非常全面。如果您想了解更多信息,可以快速入门,并继续阅读。除了一些基本的应用程序安全性术语外,它还涵盖了Spring Security可以做的所有事情。或者至少您可能会喜欢它,因为当您阅读某个组件时,可能会提到五个(或大约)新的相关组件。因此,这可能会让您感到不知所措。

与其他两个相比,Apache Shiro的文档介于两者之间。它确实解释了一些基本术语和定义,以及Shiro本身的工作方式或可以用它完成的大部分工作。但是,请注意它被称为“大多数”,而不是“全部”,因为您可能会遇到一些空的“ TODO”部分。

使用方便

对于使用声明式样式的非常基本的配置,这三者都同样容易,其中Shiro处于领先地位,而Java EE Security则处于落后地位,而Spring Security处于中间位置。

Apache Shiro示例

Shiro的声明式配置风格真正令人感到满意的是它的光滑度(甚至 看起来不错)和简单。您将配置写入一个简单的INI文件中。XML仅用于启用Shiro本身。

这是您的shiro.ini外观:

[main]

# login / logout configuration | authc = shiro standard FormAuthenticationFilter

authc.loginUrl = /login.html # specifying which URL to redirect to, when Shiro attempts to authenticate a user via authc

authc.successUrl = /index.html # the redirect-URL after a successful login

logout.redirectUrl = /logout.html # the redirect-URL after a successful logout

[users]

# define some test users

jan = passwort, employer # format: username = password[, role1[, role2[, roleN]]]

naj = passwort, employee

ajn = passwort

[roles]

# define permissions for roles

employer = * # granted all permissions

employee = shop:browse:* # granted permission to browse the shop and do any related action

[urls]

# protect urls

/login.html = authc # this step is necessary to register /login.html as the loginUrl of the authc filter

/index.html = authc # catch requests to /index.html and let the authc filter process them

/ = authc # same as above

# specify logout url

/logout = logout # catch requests to /logout and let the logout filter process them

# REST urls | noSessionCreation is used to avoid creation of sessions | authcBasic = shiro's standard BasicHttpAuthenticationFilter

/rest/shop/browse/** = noSessionCreation, authcBasic, perms["shop:browse:*"] # the perms filter additionally checks the subject for the specified permissions

/rest/shop/add = noSessionCreation, authcBasic, roles[employer] # the roles filter checks the subject for the specified roles

/rest/shop/delete/* = noSessionCreation, authcBasic, roles[employer]

Java EE安全性示例

相比之下,通过web.xml配置Java EE Security有点累。但是,最大的缺点是仅凭web.xml不能满足要求。您还必须配置您的应用程序服务器。当尝试实现更高级的功能(例如JDBC领域)时,这可能会令人感到沮丧。

请注意,除了/index.html外,没有其他受保护的URL。REST URL使用注解进行保护,在这种情况下,这样做较为容易。几乎快要看到胖的<security-constraint>元素了吗?与shiro.ini相比,您比实际规则更忙于编写元素名称。对于小型应用程序,这似乎并不重要,因为您可以指定多个<url-pattern>。但是想象一下,编写具有更多角色和规则来实施和保护URL的代码。

例:

<web-app xmlns:xsi="http://www./2001/XMLSchema-instance"

xmlns="http://xmlns./xml/ns/javaee"

xsi:schemaLocation="http://xmlns./xml/ns/javaee http://xmlns./xml/ns/javaee/web-app_3_1.xsd"

version="3.1">

<display-name>PetShop</display-name>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

<servlet>

<servlet-name>Logout</servlet-name>

<servlet-class>src.servlet.Logout</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>Logout</servlet-name>

<url-pattern>/logout</url-pattern>

</servlet-mapping>

<context-param>

<param-name>resteasy.role.based.security</param-name> <!-- turn on JAX-RS Annotations -->

<param-value>true</param-value>

</context-param>

<login-config> <!-- configure authentication -->

<auth-method>FORM</auth-method> <!-- form-based authentication chosen -->

<realm-name>secureDomain</realm-name> <!-- name of your security realm on the application server -->

<form-login-config> <!-- specify the login and error page -->

<form-login-page>/login.html</form-login-page>

<form-error-page>/error.html</form-error-page>

</form-login-config>

</login-config>

<security-constraint> <!-- here you can make a set of URL's only accessible to certain user roles -->

<web-resource-collection> <!-- you can also specify wich HTTP methods have to be protected -->

<web-resource-name>Some name</web-resource-name>

<url-pattern>/index.html</url-pattern> <!-- the URL pattern to be protected -->

</web-resource-collection>

<auth-constraint> <!-- the set of roles which are granted access to the URL's specified in <web-resource-collection> -->

<role-name>employer</role-name>

<role-name>employee</role-name>

</auth-constraint>

</security-constraint>

<security-role> <!-- the security roles used by the application -->

<role-name>employer</role-name>

</security-role>

<security-role>

<role-name>employee</role-name>

</security-role>

</web-app>

Spring安全示例

Spring Security的基本配置非常简单。它甚至可能比Shiro的要容易一些。它将创建一个登录页面(如果您没有登录页面),并添加针对CSRF和会话固定的保护。不过,自动保护最适合JSP。对于HTML,变通办法将是必需的。

要实现自定义组件,您将必须学习XML中的bean定义以及Spring的注入。这可能会导致大量的bean声明,从而使.xml难以阅读。另外,使用批注还需要进一步的Spring或AspectJ依赖性。

例:

9cf497a520e.jpeg

<beans:beans xmlns="http://www./schema/security"

xmlns:beans="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance"

xsi:schemaLocation="http://www./schema/beans

http://www./schema/beans/spring-beans.xsd

http://www./schema/security

http://www./schema/security/spring-security.xsd">

<!-- use the <http> element to configure a filter chain -->

<http pattern="/rest/**" create-session="never"> <!-- apply chain on a specific URL using 'pattern' | control session creation using 'create-session' -->

<intercept-url pattern="/**" access="hasRole('EMPLOYER')" /> <!-- access to every URL following /rest/ is restricted to the 'EMPLOYER' role -->

<http-basic /> <!-- turn on HTTP Basic Authentication -->

</http>

<http> <!-- a <http> element without a pattern attribute is applied to all incoming requests that are not caught by other <http> elements before it -->

<intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" /> <!-- grant everyone access to /login.html -->

<intercept-url pattern="/index.jsp" access="hasRole('EMPLOYEE') or hasRole('EMPLOYER')" /> <!-- restrict access to index.jsp to subjects in the 'EMPLOYEE' or 'EMPLOYER' role -->

<form-login login-page="/login.jsp" default-target-url="/index.jsp"

always-use-default-target="true" /> <!-- turn on form authentication, set default success url, tell spring to always use that url -->

<logout /> <!-- turn on logout -->

<remember-me /> <!-- turn on remember me -->

<csrf disabled="true" /> <!-- turn on csrf protection -->

</http>

<authentication-manager> <!-- turn on authentication services -->

<authentication-provider> <!-- compares the supplied username/password combination with the ones stored in <user-service> -->

<user-service> <!-- store username/password pairs in-memory -->

<user name="jan" password="passwort" authorities="ROLE_EMPLOYER" />

<user name="naj" password="passwort" authorities="ROLE_EMPLOYEE" />

</user-service>

</authentication-provider>

</authentication-manager>

</beans:beans>

社区支持

这里没有太多要说的,因为与其他两个相比,Spring Security具有庞大的社区。关于Spring Security的Stack Overflow(SO)有很多问题和答案,因此最有可能至少找到一些问题的提示。此外,不再支持官方论坛,它们仅在阅读模式下可用。支持已移至SO。在那里,国防部监视某些标签。

对Shiro的支持相当“不错”。有一个官方用户论坛,活动活跃。在其他资源上寻求帮助不会产生更多的结果。您可能会看到相同的人(例如原始开发人员Lez Hazelwood)在受欢迎的网站(例如SO)上回答问题,这不一定是不好的。解决意外问题可能需要一些时间。

关于Java EE安全性支持的最糟糕的事情是,您还必须依赖于所使用容器的社区。因此,解决问题所需的支持,精力和时间会有所不同。

但是,这三个都在积极发展中。尽管Java EE Security通过Soteria API(Java EE 8)获得了新功能,但Spring Security和Shiro仍在不断改进。

特色功能

d8ebb80dff2.jpeg

Shiro的简单性和灵活性令人赞叹。INI配置进一步强调了这一点。Shiro还建议尽可能独立于其他技术。它还需要很少的依赖关系,使其轻量级。非Web应用程序(例如CLI客户端或移动应用程序)的会话管理和通配符许可语法也很重要。

Spring Security的自动保护机制使它在Web应用程序的上下文中具有最初的优势。总的来说,可以说该框架在网络方面是相对全面的。但是,这是以牺牲自己的体重为代价的,并且在某些情况下必须绑定到Spring技术。与Shiro的通配符权限语法相反,Spring Security中的权限可以基于Spring EL来实现。

此处缺少Java EE安全性。换句话说,它确实不提供任何出色的功能,仅满足应用程序安全性的最基本需求。

结论

如果您的应用程序非常小,用户和角色没有太多,并且不需要使用任何过于高级的功能,请随时使用Java EE Security。为此,它提供了坚实的基础。但是,Java EE安全性的可能性很快就被耗尽了。例如,您只能为整个应用程序指定一种身份验证机制。另外,如果应用程序需要可移植,则一定要使用其他两个框架之一。

现在,如果需要一个很大程度上独立的,轻量级的和可扩展的安全解决方案,那么Apache Shiro是必经之路。但是,不利的一面是可能需要花费一些时间才能解决问题。一个人可能还必须自己实现一些功能。Shiro的设计(基于接口的驱动和基于POJO的)促进了这一点。

最后,如果该应用程序已经基于Spring,那么不妨继续使用Spring Security,在这种情况下没有任何实际的缺点(除了Spring Security难以实现)。对于没有弹簧的应用程序,这是不同的,即使以前从未使用过Spring,也是如此。首先,更难实现高级功能,除非包含Spring本身或AspectJ,否则不能使用注释。另外,如果需要Spring OAuth2,则必须使用spring-mvc而不是Jersey或RESTeasy来创建REST资源。

至此,我们的比较结束了。再次提醒我们有关观测的相对性。自己尝试框架,并使用最适合您需求的框架。

==============================================================

相对于Apache Shiro,Spring Security提供了更多的诸如LDAP、OAuth2.0、ACL、Kerberos、SAML、SSO、OpenID等诸多的安全认证、鉴权协议,可以按需引用。对认证/鉴权更加灵活,粒度更细。可以结合你自己的业务场景进行更加合理的定制化开发。在最新的Spring Security 5.x中更是提供了响应式应用(reactive application)提供了安全控制支持。从语言上来讲,支持使用kotlin、groovy进行开发。Spring Security因为是利用了Spring IOC 和AOP的特性而无法脱离Spring独立存在。

而Apache Shiro可以独立存在。但是Java Web领域Spring可以说是事实上的J2EE规范。使用Java技术栈很少能脱离Spring。也因为功能强大Spring Security被认为非常重,这是不对的。认真学习之后会发现其实也就是那么回事。两种框架都是非常优秀的安全框架,根据实际需要做技术选型。

如果你使用微服务建议使用 Spring Seucurity ,比较简单的应用可以使用Shiro。Spring Seucurity 学习起来也不难,我出了一个从零开始的Spring Security教程,目前广受好评,你可以到我个人博客felord.cn去免费获取。


没有强不强一说,他们都是实现系统角色权限认证的框架,多数情况下并不是拿来即用,而是需要针对不同的项目进行扩展开发,二次开发。如果你对他们了解的深,很清楚的明白过滤器链等底层实现原理,那就可以让他们变得更强。开发者强,框架就强。框架只是给你一个通用的解决方案,强不强的还是在开发者怎么样去改造使用它。

另外,即使是在微服务时代,shiro也很好用,可以改造stateless模式就可以达到和spring security一样的效果了,重点是轻量级!上手快!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多