
- Spring Security 教程
- Spring Security - 首頁
- Spring Security - 簡介
- Spring Security - 架構
- Spring Security - 專案模組
- Spring Security - 環境設定
- Spring Security - 表單登入
- Spring Security - 自定義表單登入
- Spring Security - 登出
- Spring Security - 記住我
- Spring Security - 重定向
- Spring Security - 標籤庫
- Spring Security - XML 配置
- Spring Security - 認證提供程式
- Spring Security - 基本認證
- Spring Security - AuthenticationFailureHandler
- Spring Security - JWT
- Spring Security - 獲取使用者資訊
- Spring Security - Maven
- Spring Security - 預設密碼編碼器
- Spring Security – 密碼編碼
- Spring Security - 方法級別
- Spring Security 有用資源
- Spring Security - 快速指南
- Spring Security - 有用資源
- Spring Security - 討論
Spring Security - 自定義表單登入
基於表單的登入是 Spring Security 提供支援的一種使用者名稱/密碼身份驗證形式。這透過一個 HTML 表單提供。
每當使用者請求受保護的資源時,Spring Security 都會檢查請求的身份驗證。如果請求未經身份驗證/授權,則使用者將被重定向到登入頁面。登入頁面必須以某種方式由應用程式呈現。Spring Security 預設情況下提供該登入表單,正如我們在Spring Security - 表單登入章節中看到的。
在大多數生產案例中,登入頁面都是自定義的,並且必須像下面這樣顯式提供 -
protected void configure(HttpSecurity http) throws Exception { http // ... .authorizeHttpRequests( request -> request.requestMatchers("/login").permitAll() .requestMatchers("/**").authenticated() ) .formLogin(form -> form.loginPage("/login").permitAll()) }
讓我們開始使用 Spring Security 進行實際程式設計。在開始使用 Spring 框架編寫示例之前,您必須確保已正確設定 Spring 環境,如Spring Security - 環境設定章節中所述。我們還假設您對 Spring Tool Suite IDE 有基本的瞭解。
現在讓我們繼續編寫一個由 Maven 管理的基於 Spring MVC 的應用程式,該應用程式將要求使用者登入、對使用者進行身份驗證,然後使用 Spring Security 表單登入功能提供登出選項。
使用 Spring Initializr 建立專案
Spring Initializr 是開始 Spring Boot 專案的好方法。它提供了一個易於使用的使用者介面來建立專案、新增依賴項、選擇 Java 執行時等。它生成一個骨架專案結構,一旦下載,就可以匯入到 Spring Tool Suite 中,然後我們可以繼續使用我們的現成專案結構。
我們選擇了一個 Maven 專案,將專案命名為 formlogin,Java 版本為 21。添加了以下依賴項
Spring Web
Spring Security
Spring Boot DevTools

Thymeleaf 是 Java 的模板引擎。它允許我們快速開發靜態或動態網頁以在瀏覽器中呈現。它具有極強的可擴充套件性,允許我們詳細定義和自定義模板的處理。此外,我們可以透過點選此連結瞭解更多關於 Thymeleaf 的資訊。
讓我們繼續生成我們的專案並下載它。然後我們將它解壓縮到我們選擇的資料夾中,並使用任何 IDE 開啟它。我將使用Spring Tools Suite 4。它可以從https://springframework.tw/tools網站免費下載,並且針對 Spring 應用程式進行了最佳化。
包含所有相關依賴項的 pom.xml
讓我們看看我們的 pom.xml 檔案。它應該看起來類似於以下內容 -
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>3.3.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.tutorialspoint.security</groupId> <artifactId>formlogin</artifactId> <version>0.0.1-SNAPSHOT</version> <name>formlogin</name> <description>Demo project for Spring Boot</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>21</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <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.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity6</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-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>
Login.html
此程式碼需要在對映的資料夾中存在一個 login.html 檔案,該檔案將在訪問 /login 時返回。此 HTML 檔案應包含一個登入表單。此外,請求應為 POST 請求到 /login。引數名稱應分別為“username”和“password”以表示使用者名稱和密碼。
在/src/main/resources/templates資料夾中建立 login.html,內容如下,用作登入頁面。
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}"> <p>Bad Credentials</p> </div> <div th:if="${param.logout}">You have been logged out.</div> <form th:action="@{/login}" method="post"> <div> <h1>Please sign in</h1> <label for="username"><b>Username</b></label> <input type="text" placeholder="Enter Username" name="username" id="username" required> <label for="password"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="password" id="password" required> <input type="submit" value="Sign In" /> </div> </form> </body> </html>
更新 Spring Security 配置類
在我們的 config 包中,我們有 WebSecurityConfig 類,如Spring Security - 表單登入章節中所定義。讓我們更新其 filterChain() 方法以用於我們的自定義登入頁面
http. //... .formLogin(form -> form.loginPage("/login") .defaultSuccessUrl("/") .failureUrl("/login?error=true") .permitAll()) //... .build();
以下是 Spring Security 配置類的完整程式碼
WebSecurityConfig.java
package com.tutorialspoint.security.formlogin.config; 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.configurers.AbstractHttpConfigurer; 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.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean protected UserDetailsService userDetailsService() { UserDetails user = User.builder() .username("user") .password(passwordEncoder().encode("user123")) .roles("USER") .build(); UserDetails admin = User.builder() .username("admin") .password(passwordEncoder().encode("admin123")) .roles("USER", "ADMIN") .build(); return new InMemoryUserDetailsManager(user, admin); } @Bean protected PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests( request -> request.requestMatchers("/login").permitAll() .requestMatchers("/**").authenticated() ) .formLogin(form -> form.loginPage("/login") .defaultSuccessUrl("/") .failureUrl("/login?error=true") .permitAll()) .logout(config -> config .logoutUrl("/logout") .logoutSuccessUrl("/login")) .build(); } }
這裡有幾點需要注意 -
defaultSuccessUrl ("/") − 此端點將作為我們的應用程式的首頁和成功頁面。正如我們之前配置的那樣,我們將保護此頁面,並且只有經過身份驗證的使用者才能訪問此頁面。
failureUrl ("/login?error=true") − 此端點將載入帶有錯誤標誌的登入頁面以顯示錯誤訊息。
logoutUrl ("/logout") − 這將用於登出我們的應用程式。
logoutSuccessUrl ("/login") − 這將用於在使用者成功登出後加載登入頁面。
控制器類
在這個類中,我們為“/”端點和“/login”端點建立了對映,分別用於此應用程式的首頁和登入頁面。
AuthController.java
package com.tutorialspoint.security.formlogin.controllers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class AuthController { @GetMapping("/") public String home() { return "index"; } @GetMapping("/login") public String login() { return "login"; } }
檢視
讓我們更新/src/main/resources/templates資料夾中的 index.html,內容如下,用作首頁並顯示已登入的使用者名稱。
index.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-springsecurity6"> <head> <title> Hello World! </title> </head> <body> <h1 th:inline="text">Hello <span sec:authentication="name"></span>!</h1> <form th:action="@{/logout}" method="post"> <input type="submit" value="Sign Out"/> </form> </body> <html>
login.html
讓我們在/src/main/resources/templates資料夾中建立 login.html,內容如下,用作登入頁面。我們使用預設名稱username和password作為文字欄位。如果使用其他名稱,我們也需要在 Spring Security 配置類中設定相同的名稱。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6"> <head> <title>Spring Security Example</title> </head> <body> <div th:if="${param.error}"> <p>Bad Credentials</p> </div> <div th:if="${param.logout}">You have been logged out.</div> <form th:action="@{/login}" method="post"> <div> <h1>Please sign in</h1> <label for="username"> <b>Username</b> </label> <input type="text" placeholder="Enter Username" name="username" id="username" required> <label for="password"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="password" id="password" required> <input type="submit" value="Sign In" /> </div> </form> </body> </html>
在 login.html 中,我們使用${param.error}讀取請求引數error。如果為真,則列印錯誤訊息Bad Credential。類似地,我們使用${param.logout}讀取請求引數logout。如果為真,則列印登出訊息。
在登入表單中,我們使用 POST 方法登入,同時使用名稱和 ID 分別為username和password的輸入欄位。
執行應用程式
由於我們已經準備好所有元件,讓我們執行應用程式。右鍵單擊專案,選擇Run As,然後選擇Spring Boot App。
它將啟動應用程式,並且應用程式啟動後,我們可以執行 localhost:8080 以檢查更改。
輸出
現在開啟 localhost:8080,您可以看到我們的自定義登入頁面。
登入頁面

錯誤憑據的登入頁面
輸入任何無效的憑據,它將顯示錯誤。

主頁
輸入有效的憑據

它將載入主頁。

登出後
現在單擊登出按鈕,這將再次載入登入頁面。
