1.概述
本教程显示了如何使用Spring和基于Java的Spring Security 3.1来保护REST服务 。 本文将重点介绍如何使用“登录和Cookie”方法专门针对REST API设置安全配置。
2.
Spring Security的体系结构完全基于Servlet过滤器,因此,在HTTP请求处理方面,Spring Security早于Spring MVC。 请记住,首先,需要在应用程序的web.xml中声明一个过滤器 :
<filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
该过滤器必须被命名为“ springSecurityFilterChain”,以匹配Spring Security在容器中创建的默认bean。
注意,定义的过滤器不是实现安全性逻辑的实际类,而是DelegatingFilterProxy ,其目的是将Filter的方法委托给内部Bean。 这样做是为了使目标bean仍然可以从Spring上下文生命周期和灵活性中受益。
用于配置过滤器的URL模式/ *即使整个Web服务被映射到/ API / *,这样的安全配置有如果需要,以确保其它可能的映射以及选项。
3.安全配置
<?xml version="1.0" encoding="UTF-8"?>
<beans:beansxmlns="http://www.springframework.org/schema/security"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:beans="http://www.springframework.org/schema/beans"xmlns:sec="http://www.springframework.org/schema/security"xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><http entry-point-ref="restAuthenticationEntryPoint"><intercept-url pattern="/api/admin/**" access="ROLE_ADMIN"/><form-login authentication-success-handler-ref="mySuccessHandler" /><logout /></http><beans:bean id="mySuccessHandler"class="org.rest.security.MySavedRequestAwareAuthenticationSuccessHandler"/><authentication-manager alias="authenticationManager"><authentication-provider><user-service><user name="temporary" password="temporary" authorities="ROLE_ADMIN"/><user name="user" password="user" authorities="ROLE_USER"/></user-service></authentication-provider></authentication-manager></beans:beans>
大多数配置都是使用安全性名称空间完成的-要启用此功能,必须定义架构位置并指向正确的3.1 XSD版本。 命名空间的设计使其能够表达Spring Security的常用用法,同时仍提供钩子原始bean来容纳更高级的场景。
3.1。 <http>元素
<http>元素是HTTP安全配置的主要容器元素。 在当前的实现中,它仅确保了一个映射: / api / admin / ** 。 注意,映射是相对于 Web应用程序的根上下文的,而不是相对于其余 Servlet的。 这是因为整个安全配置都存在于Spring的根上下文中,而不是在Servlet的子上下文中。
3.2。 入口点
在标准的Web应用程序中,当客户端尝试访问未经身份验证的安全资源时,身份验证过程可能会自动触发-这通常是通过重定向到登录页面以使用户可以输入凭据来完成的。 但是,对于REST Web服务,此行为没有多大意义-身份验证仅应通过对正确URI的请求来完成,而所有其他请求如果未通过身份验证,则应仅以401 UNAUTHORIZED状态代码失败。
Spring Security使用入口点的概念来处理自动触发的身份验证过程-这是配置的必需部分,可以通过<http>元素的entry-point-ref属性注入。 请记住,此功能在REST服务的上下文中没有意义,新的自定义入口点被定义为在被触发时仅返回401:
@Component( "restAuthenticationEntryPoint" )
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{@Overridepublic void commence( HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException{response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );}
}
3.3。 REST的登录表单
REST API的身份验证有多种方法-Spring Security提供的默认方法之一是表单登录 -使用身份验证处理过滤器– org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter 。
<form-login>元素将创建此过滤器,还将允许我们在其上设置自定义身份验证成功处理程序。 也可以通过使用<custom-filter>元素在FORM_LOGIN_FILTER位置注册过滤器来手动完成–但是名称空间支持足够灵活。
请注意,对于标准Web应用程序, <http>元素的auto-config属性是一些有用的安全配置的简写语法。 尽管这对于某些非常简单的配置可能是适当的,但它并不适合并且不应用于REST API。
3.4。 身份验证应返回200而不是301
默认情况下,表单登录将使用301 MOVED PERMANENTLY状态代码回答成功的身份验证请求; 这在实际登录表单的上下文中是有意义的,该表单需要在登录后进行重定向。 但是,对于RESTful Web服务,成功身份验证所需的响应应为200 OK 。
这是通过在表单登录过滤器中注入自定义身份验证成功处理程序来完成的,以替换默认的成功处理程序 。 新的处理程序实现与默认的org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler完全相同的登录名,但有一个显着的区别–删除了重定向逻辑:
public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {private RequestCache requestCache = new HttpSessionRequestCache();@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {SavedRequest savedRequest = requestCache.getRequest(request, response);if (savedRequest == null) {clearAuthenticationAttributes(request);return;}String targetUrlParam = getTargetUrlParameter();if (isAlwaysUseDefaultTargetUrl() || (targetUrlParam != null && StringUtils.hasText(request.getParameter(targetUrlParam)))) {requestCache.removeRequest(request, response);clearAuthenticationAttributes(request);return;}clearAuthenticationAttributes(request);}public void setRequestCache(RequestCache requestCache) {this.requestCache = requestCache;}
}
3.5。 身份验证管理器和提供程序
身份验证过程使用内存中的提供程序执行身份验证-这是为了简化配置,因为这些工件的生产实现不在本文讨论范围之内。
3.6最后–针对正在运行的REST服务进行身份验证
现在,让我们看看如何针对REST API进行身份验证-登录的URL为/ j_spring_security_check-以及执行登录的简单curl命令为:
curl -i -X POST -d j_username=user -d j_password=userPass
http://localhost:8080/spring-security-rest/j_spring_security_check
该请求将返回Cookie,随后针对REST服务的任何后续请求都将使用该Cookie。
我们可以使用curl进行身份验证并将收到的cookie存储在文件中 :
curl -i -X POST -d j_username=user -d j_password=userPass -c /opt/cookies.txt
http://localhost:8080/spring-security-rest/j_spring_security_check
然后, 我们可以使用文件中的cookie进行进一步的身份验证请求:
curl -i --header "Accept:application/json" -X GET -b /opt/cookies.txt
http://localhost:8080/spring-security-rest/api/foos
经过身份验证的请求将正确显示200 OK :
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 24 Jul 2013 20:31:13 GMT[{"id":0,"name":"JbidXc"}]
4. Maven和其他麻烦
Web应用程序和REST服务所需的Spring 核心依赖关系已详细讨论。 为了安全起见,我们需要添加: spring-security-web和spring-security-config-所有这些都已在Maven for Spring Security教程中进行了介绍。
值得密切关注Maven解决旧版Spring依赖项的方式–一旦将安全工件添加到pom中,解析策略将开始引起问题 。 为了解决这个问题,一些核心依赖项将需要被覆盖,以使其保持在正确的版本。
5.结论
这篇文章涵盖了使用Spring Security 3.1的RESTful服务的基本安全配置和实现,讨论了web.xml ,安全配置,用于身份验证过程的HTTP状态代码以及安全工件的Maven解析。
可以在github项目中找到该Spring Security REST教程的实现–这是一个基于Eclipse的项目,因此应该很容易直接导入和运行。
翻译自: https://www.javacodegeeks.com/2011/11/securing-restful-web-service-with.html