原标題:Spring認證指南:了解如何使用 Spring Security 保護您的 Web 應用程式。(Spring中國教育管理中心)
保護 Web 應用程式
本指南将引導您完成使用受 Spring Security 保護的資源建立簡單 Web 應用程式的過程。
你将建造什麼
您将建構一個 Spring MVC 應用程式,該應用程式使用由固定使用者清單支援的登入表單來保護頁面。
你需要什麼
- 約15分鐘
- 最喜歡的文本編輯器或 IDE
- JDK 1.8或更高版本
- Gradle 4+或Maven 3.2+
- 您還可以将代碼直接導入 IDE:
- 彈簧工具套件 (STS)
- IntelliJ IDEA
如何完成本指南
像大多數 Spring入門指南一樣,您可以從頭開始并完成每個步驟,也可以繞過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到工作代碼。
要從頭開始,請繼續從 Spring Initializr 開始。
要跳過基礎知識,請執行以下操作:
- 下載下傳并解壓本指南的源代碼庫,或使用Git克隆它:git clone https://github.com/spring-guides/gs-securing-web.git
- CD光牒進入gs-securing-web/initial
- 繼續建立不安全的 Web 應用程式。
完成後,您可以對照中的代碼檢查結果gs-securing-web/complete。
從 Spring Initializr 開始
您可以使用這個預先初始化的項目并單擊 Generate 下載下傳 ZIP 檔案。此項目配置為适合本教程中的示例。
手動初始化項目:
- 導航到https://start.spring.io。該服務提取應用程式所需的所有依賴項,并為您完成大部分設定。
- 選擇 Gradle 或 Maven 以及您要使用的語言。本指南假定您選擇了 Java。
- 單擊Dependencies并選擇Spring Web和Thymeleaf。
- 單擊生成。
- 下載下傳生成的 ZIP 檔案,該檔案是根據您的選擇配置的 Web 應用程式的存檔。
如果您的 IDE 具有 Spring Initializr 內建,您可以從您的 IDE 完成此過程。
你也可以從 Github 上 fork 項目并在你的 IDE 或其他編輯器中打開它。
建立不安全的 Web 應用程式
在将安全性應用到 Web 應用程式之前,您需要一個 Web 應用程式來保護。本部分将引導您建立一個簡單的 Web 應用程式。然後,您将在下一節中使用 Spring Security 對其進行保護。
Web 應用程式包括兩個簡單的視圖:一個首頁和一個“Hello, World”頁面。首頁在以下 Thymeleaf 模闆中定義(來自src/main/resources/templates/home.html):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h1>Welcome!</h1>
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
</body>
</html>
這個簡單的視圖包含一個指向/hello頁面的連結,該連結在以下 Thymeleaf 模闆中定義(來自src/main/resources/templates/hello.html):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Web 應用程式基于 Spring MVC。是以,您需要配置 Spring MVC 并設定視圖控制器來公開這些模闆。以下清單(來自src/main/java/com/example/securingweb/MvcConfig.java)顯示了在應用程式中配置 Spring MVC 的類:
package com.example.securingweb;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
該addViewControllers()方法(覆寫 中的同名方法WebMvcConfigurer)添加了四個視圖控制器。兩個視圖控制器引用名稱為home(定義在home.html)的視圖,另一個引用名為hello(定義在hello.html)的視圖。第四個視圖控制器引用另一個名為login. 您将在下一節中建立該視圖。
此時,您可以跳轉到“運作應用程式”并運作應用程式,而無需登入任何東西。
現在您有了一個不安全的 Web 應用程式,您可以為其添加安全性。
設定 Spring Security
假設您要防止未經授權的使用者檢視 的問候語頁面/hello。就像現在一樣,如果通路者點選首頁上的連結,他們會看到沒有阻止他們的障礙。您需要添加一個障礙,強制通路者在看到該頁面之前登入。
您可以通過在應用程式中配置 Spring Security 來做到這一點。如果 Spring Security 在類路徑上,Spring Boot 會自動使用“基本”身份驗證保護所有 HTTP 端點。但是,您可以進一步自定義安全設定。您需要做的第一件事是将 Spring Security 添加到類路徑中。
使用 Gradle,您需要在 in 的dependencies閉包中添加兩行(一行用于應用程式,一行用于測試) build.gradle,如以下清單所示:
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
以下清單顯示了完成的build.gradle檔案:
plugins {
id 'org.springframework.boot' version '2.6.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
test {
useJUnitPlatform()
}
使用 Maven,您需要向 中的<dependencies>元素添加兩個額外的條目(一個用于應用程式,一個用于測試) pom.xml,如以下清單所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
以下清單顯示了完成的pom.xml檔案:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>securing-web-complete</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>securing-web-complete</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
以下安全配置(來自src/main/java/com/example/securingweb/WebSecurityConfig.java)確定隻有經過身份驗證的使用者才能看到秘密問候:
package com.example.securingweb;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
該類WebSecurityConfig被注釋@EnableWebSecurity為啟用 Spring Security 的 Web 安全支援并提供 Spring MVC 內建。它還擴充WebSecurityConfigurerAdapter和覆寫了它的幾個方法來設定 Web 安全配置的一些細節。
該configure(HttpSecurity)方法定義了哪些 URL 路徑應該被保護,哪些不應該。具體來說,/和/home路徑被配置為不需要任何身份驗證。所有其他路徑都必須經過身份驗證。
當使用者成功登入時,他們将被重定向到先前請求的需要身份驗證的頁面。有一個自定義/login頁面(由 指定loginPage()),每個人都可以檢視。
該userDetailsService()方法使用單個使用者設定記憶體中的使用者存儲。該使用者的使用者名是user,密碼是password,角色是USER。
現在您需要建立登入頁面。該視圖已經有一個視圖控制器login,是以您隻需要建立登入視圖本身,如以下清單(來自src/main/resources/templates/login.html)所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
這個 Thymeleaf 模闆提供了一個表單,該表單捕獲使用者名和密碼并将它們釋出到/login. 按照配置,Spring Security 提供了一個過濾器來攔截該請求并對使用者進行身份驗證。如果使用者未能通過身份驗證,頁面将被重定向到/login?error,并且您的頁面會顯示相應的錯誤消息。成功退出後,您的應用程式将發送到/login?logout,并且您的頁面會顯示相應的成功消息。
最後,您需要為通路者提供一種顯示目前使用者名和登出的方式。為此,請更新hello.html以向目前使用者問好并包含一個Sign Out表單,如以下清單(來自src/main/resources/templates/hello.html)所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
我們通過使用 Spring Security 與HttpServletRequest#getRemoteUser(). “退出”表單送出 POST 到/logout. 成功登出後,它将使用者重定向到/login?logout.
運作應用程式
Spring Initializr 為您建立了一個應用程式類。在這種情況下,您不需要修改類。以下清單(來自src/main/java/com/example/securingweb/SecuringWebApplication.java)顯示了應用程式類:
package com.example.securingweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SecuringWebApplication {
public static void main(String[] args) throws Throwable {
SpringApplication.run(SecuringWebApplication.class, args);
}
}
建構一個可執行的 JAR
您可以使用 Gradle 或 Maven 從指令行運作應用程式。您還可以建構一個包含所有必要依賴項、類和資源的單個可執行 JAR 檔案并運作它。建構可執行 jar 可以在整個開發生命周期、跨不同環境等中輕松地作為應用程式傳遞、版本化和部署服務。
如果您使用 Gradle,則可以使用./gradlew bootRun. 或者,您可以使用建構 JAR 檔案./gradlew build,然後運作 JAR 檔案,如下所示:
java -jar build/libs/gs-securering-web-0.1.0.jar
如果您使用 Maven,則可以使用./mvnw spring-boot:run. 或者,您可以使用建構 JAR 檔案,./mvnw clean package然後運作該 JAR 檔案,如下所示:
java -jar 目标/gs-securering-web-0.1.0.jar
此處描述的步驟建立了一個可運作的 JAR。您還可以建構經典的 WAR 檔案。
應用程式啟動後,将浏覽器指向http://localhost:8080. 您應該會看到首頁,如下圖所示:
應用程式的首頁
當您單擊該連結時,它會嘗試将您帶到位于 的問候語頁面/hello。但是,由于該頁面是安全的并且您還沒有登入,它會将您帶到登入頁面,如下圖所示:
登入頁面
如果您使用不安全版本跳到此處,則看不到登入頁面。您應該備份并編寫其餘基于安全性的代碼。
在登入頁面,分别輸入使用者名和密碼字段,以測試使用者身份user登入password。送出登入表單後,您将通過身份驗證,然後進入歡迎頁面,如下圖所示:
安全的問候頁面
如果您單擊登出按鈕,您的身份驗證将被撤銷,您将傳回登入頁面,并顯示一條消息,表明您已登出。
概括
恭喜!您已經開發了一個使用 Spring Security 保護的簡單 Web 應用程式。