Spring Security學習(二)Spring Security Guides
配置方式
主要有四種配置方式
- Hello Spring Security Java Config
- Hello Spring Security with Boot
- Hello Spring Security Xml Config
- Hello Spring MVC Security Java Config
我根據需要,主要參考了Hello Spring Security Xml Config和Hello Spring MVC Security Java Config。
啟動示例
本節概述如何在Spring Tool Suite(STS)中設定工作區,以便您可以遵循本指南。下一節將介紹如何將Spring Security應用於現有應用程式的通用步驟。雖然您可以簡單地將步驟應用於現有應用程式,但我們鼓勵您遵循本指南,以減少複雜性。
獲取示例專案
匯入不安全的MVC示例應用程式
為了遵循,我們建議您將insecuremvc示例應用程式匯入到IDE中。您可以使用任何您喜歡的IDE,但本指南中的說明將假設您正在使用Spring Tool Suite(STS)。
完整的示例應用程式可以在SPRING_SECURITY_HOME/samples/javaconfig/helloworld中找到
- 啟動STS並將示例應用程式匯入STS,步驟如下:
- File→Import
- Existing Maven Projects
- Click Next >
- Click Browse…
- Navigate to the samples (i.e. SPRING_SECURITY_HOME/samples/xml/insecure) and click OK
- Click Finish
執行insecuremvc應用程式
在下面的練習中,我們將修改spring-security-samples-xml-insecuremvc應用程式。在進行任何更改之前,最好驗證示例是否正常工作。執行以下步驟以確保spring-security-samples-xml-insecuremvc可以正常工作。
- Right click on the spring-security-samples-xml-insecuremvc application
- Select Run As→Run on Server
- Select the latest tc Server
- Click Finish
驗證應用程式是否正常工作:
- 使用者收件箱的頁面可以在http//localhost8080/sample/顯示TODO Secure
驗證應用程式執行後,請使用以下步驟停止應用程式伺服器:
- 在“伺服器”檢視中,選擇最新的tc伺服器
- 單擊停止按鈕(紅色方塊)停止應用程式伺服器
保護應用程式
在保護您的應用程式之前,確保現有應用程式的工作原理與執行不安全應用程式一樣重要。現在應用程式執行沒有安全性,我們已經準備好向我們的應用程式新增安全性。本節演示了將Spring Security新增到我們的應用程式的最小步驟。
更新你的依賴
Spring Security GA版本包含在Maven Central中,因此不需要額外的Maven儲存庫。
為了使用Spring Security,您必須新增必要的依賴關係。對於示例,我們將新增以下Spring Security依賴項:
pom.xml
<dependencies>
<!-- ... other dependency elements ... -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
</dependencies>
完成此操作後,您需要確保STS通過以下方式瞭解更新的依賴關係:
- Right click on the spring-security-samples-xml-insecuremvc application
- Select Maven→Update project…
- Ensure the project is selected, and click OK
建立您的Spring Security配置
下一步是建立一個Spring Security配置
- In the Package Explorer view, right click on the folder src/main/webapp
- Select New→Folder
- Enter WEB-INF/spring for the Folder name
- Then right click on the new folder WEB-INF/spring
- Select New→File
- Enter security.xml for the File name
- Click Finish
- Replace the contents of the file with the following:
src/main/webapp/WEB-INF/spring/security.xml
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="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
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<http />
<user-service>
<user name="user" password="password" authorities="ROLE_USER" />
</user-service>
</b:beans>
security-config-xml將:
- 需要驗證您的應用程式中的每個URL
- 為您生成登入表單
- 允許具有使用者名稱user和密碼password的使用者使用基於表單的身份驗證進行身份驗證
- 允許使用者登出
- 預防CSRF攻擊
- 會話固定保護
- 安全頭整合
- HTTP嚴格傳輸安全性用於安全請求
- X-Content-Type-Options整合
- 快取控制(可以稍後被應用程式覆蓋以允許快取靜態資源)
- X-XSS保護整合
- X-Frame-Options整合以幫助防止 Clickjacking
- 與以下Servlet API方法整合
- HttpServletRequest#getRemoteUser()
- HttpServletRequest.html#getUserPrincipal()
- HttpServletRequest.html#isUserInRole(java.lang.String)
- HttpServletRequest.html#login(java.lang.String, java.lang.String)
- HttpServletRequest.html#logout()
在war中註冊Spring Security
我們建立了Spring Security配置,但是我們仍然需要在war中註冊它。這可以通過以下步驟完成:
- In the Package Explorer view, right click on the folder src/main/webapp/WEB-INF
- Select New→File
- Enter web.xml for the File name
- Click Finish
- Replace the contents of the file with the following:
web.xml將執行以下操作:
- 為應用程式中的每個URL註冊springSecurityFilterChain過濾器
探索安全的應用程式
啟動伺服器,就像我們在執行insecuremvc應用程式一樣當您訪問http//localhost:8080/sample/時,將出現Spring Security自動生成的登入頁面。
驗證安全應用程式
嘗試輸入無效的使用者名稱和密碼:
- Username invalid
- Password invalid
您應該看到一條錯誤訊息,指出身份驗證失敗。現在嘗試輸入有效的使用者名稱和密碼:
- Username user
- Password password
您現在應該看到我們想要保護的頁面。
我們可以使用使用者名稱使用者和密碼密碼成功驗證的原因是因為這是我們在security-config-xml中配置的。
顯示使用者名稱
現在我們已經通過身份驗證,我們來更新應用程式來顯示使用者名稱。將index.jsp的body更新為以下內容:
src/main/webapp/index.jsp
<body>
<div class="container">
<h1>This is secured!</h1>
<p>
Hello <b><c:out value="${pageContext.request.remoteUser}"/></b>
</p>
</div>
</body>
標籤確保使用者名稱被轉義以避免XSS漏洞無論應用程式如何呈現使用者輸入的值,應該確保正確地轉義值。
重新整理http://localhost:8080/sample/的頁面,您將看到顯示的使用者名稱。這是因為Spring Security與Servlet API方法整合。
登出
現在我們可以檢視使用者名稱,讓我們更新應用程式以允許登出。更新index.jsp的主體以包含一個登出表單,如下所示:
src/main/webapp/index.jsp
<body>
<div class="container">
<h1>This is secured!</h1>
<p>
Hello <b><c:out value="${pageContext.request.remoteUser}"/></b>
</p>
<c:url var="logoutUrl" value="/logout"/>
<form class="form-inline" action="${logoutUrl}" method="post">
<input type="submit" value="Log out" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
</div>
</body>
為了幫助防範CSRF攻擊,預設情況下,Spring Security Java Configuration登出需要:
- HTTP方法必須是POST
- 必須將CSRF令牌新增到請求中。由於我們已經使用@EnableWebSecurity並且正在使用Thymeleaf,因此CSRF令牌會自動新增為您的隱藏輸入(檢視原始碼)。
如果您使用Spring MVC的標記庫或Thymeleaf,CSRF令牌將自動新增為隱藏的輸入。
您現在應該知道如何使用Spring Security使用XML來保護應用程式。
完整的示例應用程式可以在SPRING_SECURITY_HOME/samples/javaconfig/hellomvc中找到
執行insecuremvc應用程式
在下面的練習中,我們將修改spring-security-samples-xml-insecuremvc應用程式。在進行任何更改之前,最好驗證示例是否正常工作。執行以下步驟以確保spring-security-samples-xml-insecuremvc可以正常工作。
- Right click on the spring-security-samples-xml-insecuremvc application
- Select Run As→Run on Server
- Select the latest tc Server
- Click Finish
驗證應用程式是否正常工作:
- 使用者收件箱的頁面可以在http//localhost8080/sample/顯示
- 嘗試點選撰寫連結Compose並建立一條訊息。應顯示訊息詳細資訊。
- 現在點選收件箱Inbox連結,看到列出的訊息。您可以點選摘要連結檢視再次顯示的詳細資訊。
保護應用程式
在保護應用程式之前,確保現有應用程式的工作原理與執行insecuremvc應用程式一樣重要。現在應用程式執行沒有安全性,我們已經準備好向我們的應用程式新增安全性。本節演示了將Spring Security新增到我們的應用程式的最小步驟。
更新你的依賴
Spring Security GA版本包含在Maven Central中,因此不需要額外的Maven儲存庫。
為了使用Spring Security,您必須新增必要的依賴關係。對於示例,我們將新增以下Spring Security依賴項:
pom.xml
<dependencies>
<!-- ... other dependency elements ... -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
</dependencies>
完成此操作後,您需要確保STS通過以下方式瞭解更新的依賴關係:
- Right click on the spring-security-samples-xml-insecuremvc application
- Select Maven→Update project…
- Ensure the project is selected, and click OK
建立您的Spring Security配置
下一步是建立一個Spring Security配置
- Right click the spring-security-samples-xml-insecuremvc project in the Package Explorer view
- Select New→Class
- Enter org.springframework.security.samples.config for the Package
- Enter SecurityConfig for the Name
- Click Finish
- Replace the file with the following contents:
src/main/java/org/springframework/security/samples/config/SecurityConfig.java
package org.springframework.security.samples.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.*;
@EnableWebSecurity
public class SecurityConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
configureGlobal方法的名稱並不重要。但是,只能在使用@EnableWebSecurity,@EnableGlobalMethodSecurity或@EnableGlobalAuthentication註釋的類中配置AuthenticationManagerBuilder很重要。否則有不可預知的結果。
SecurityConfig將:
- 需要驗證您的應用程式中的每個URL
- 為您生成登入表單
- 允許具有使用者名稱user和密碼password的使用者使用基於表單的身份驗證進行身份驗證
- 允許使用者登出
- 預防CSRF攻擊
- 會話固定保護
- 安全頭整合
- HTTP嚴格傳輸安全性用於安全請求
- X-Content-Type-Options整合
- 快取控制(可以稍後被應用程式覆蓋以允許快取靜態資源)
- X-XSS保護整合
- X-Frame-Options整合以幫助防止 Clickjacking
- 與以下Servlet API方法整合
- HttpServletRequest#getRemoteUser()
- HttpServletRequest.html#getUserPrincipal()
- HttpServletRequest.html#isUserInRole(java.lang.String)
- HttpServletRequest.html#login(java.lang.String, java.lang.String)
- HttpServletRequest.html#logout()
在war中註冊Spring Security
我們建立了Spring Security配置,但是我們仍然需要在war中註冊它。這可以通過以下步驟完成:
- Right click the spring-security-samples-xml-insecuremvc project the Package Explorer view
- Select New→Class
- Enter org.springframework.security.samples.config for the Package
- Enter MessageSecurityWebApplicationInitializer for the Name
- Click Finish
- Replace the file with the following contents:
src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java
package org.springframework.security.samples.config;
import org.springframework.security.web.context.*;
public class MessageSecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
MessageSecurityWebApplicationInitializer將自動為應用程式中的每個URL註冊springSecurityFilterChain Filter。如果在其他WebApplicationInitializer例項中新增過濾器,我們可以使用@Order來控制Filter例項的排序。
驗證SecurityConfig已載入
只是因為SecurityConfig存在,並不意味著我們的Spring應用程式知道它。在這種情況下,我們的Spring根應用程式上下文使用我們的spring-security-samples-javaconfig-messages專案中包含的MessageWebApplicationInitializer進行初始化。您可以在下面找到一個程式碼段:
MessageWebApplicationInitializer.java
public class MessageWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfiguration.class };
}
// ... other overrides ...
}
您將注意到它正在載入也包含在我們的spring-security-samples-javaconfig-messages專案中的RootConfiguration類。
RootConfiguration.java
@Configuration
@ComponentScan
public class RootConfiguration {
}
@ComponentScan正在載入與RootConfiguration相同的包(和子包)中的所有配置。由於SecurityConfig是在這個包中,它將載入我們現有的設定,沒有什麼可做的。
如果沒有載入SecurityConfig,我們可以在RootConfiguration的類定義之上使用@Import(SecurityConfig.class),或者將SecurityConfig新增為getRootConfigClasses()的結果之一。
探索安全的應用程式
啟動伺服器,就像我們在執行insecuremvc應用程式一樣當您訪問http//localhost:8080/sample/時,將出現Spring Security自動生成的登入頁面。
驗證安全應用程式
嘗試輸入無效的使用者名稱和密碼:
- Username invalid
- Password invalid
您應該看到一條錯誤訊息,指出身份驗證失敗。現在嘗試輸入有效的使用者名稱和密碼:
- Username user
- Password password
您現在應該看到我們想要保護的頁面。
我們可以使用使用者名稱使用者和密碼密碼成功驗證的原因是因為這是我們在SecurityConfig中配置的。
顯示使用者名稱
現在我們已經通過身份驗證,如果使用者進行了身份驗證,我們來看看我們的應用程式如何顯示使用者名稱。
messages/src/main/resources/views/layout.html
<div th:if="${#httpServletRequest.remoteUser != null}">
<p th:text="${#httpServletRequest.remoteUser}">
sample_user
</p>
</div>
在我們的示例工程中,我們使用Thymeleaf,但任何檢視技術都可以正常工作。任何技術都可以檢查HttpServletRequest#getRemoteUser()來檢視當前使用者,因為Spring Security與Servlet API方法整合在一起。
Thymeleaf確保使用者名稱被轉義以避免XSS漏洞無論應用程式如何呈現使用者輸入的值,它應該確保值被正確地轉義。
登出
我們可以檢視使用者名稱,但是我們如何登出?下面你可以看到我們如何登出。
messages/src/main/resources/views/layout.html
<form th:action="@{/logout}" method="post">
<input type="submit" value="Log out" />
</form>
為了幫助防範CSRF攻擊,預設情況下,Spring Security Java Configuration登出需要:
- HTTP方法必須是POST
- 必須將CSRF令牌新增到請求中。由於我們已經使用@EnableWebSecurity並且正在使用Thymeleaf,因此CSRF令牌會自動新增為您的隱藏輸入(檢視原始碼)。
如果您不使用Spring MVC taglib或Thymeleaf,則可以使用屬性_csrf訪問ServletRequest上的CsrfToken。您可以在Hello Spring Security Java Config中找到將CSRF令牌包含在JSP中的示例。
重新啟動應用程式伺服器,然後單擊登出按鈕,看到應用程式成功登入。
恭喜,您現在應該知道如何使用Spring Security保護您的應用程式,而不使用任何XML了。