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