
- 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 - 標籤庫
在使用 JSP 的 Spring MVC 應用程式中,我們可以使用 Spring Security 標籤來應用安全約束以及訪問安全資訊。Spring Security 標籤庫為這些操作提供了基本支援。使用這些標籤,我們可以根據使用者的角色或許可權控制向用戶顯示的資訊。此外,我們還可以將 CSRF 保護功能包含到我們的表單中。
要使用 Spring Security 標籤,我們必須在 JSP 檔案中宣告 security 標籤庫。
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
現在,我們可以使用字首為 sec 的 Spring Security 標籤。現在讓我們看看標籤的使用方法。
authorize 標籤
我們將討論的第一個標籤是 authorize 標籤。讓我們檢視一些使用示例。
<sec:authorize access="!isAuthenticated()"> Login </sec:authorize> <sec:authorize access="isAuthenticated()"> Logout </sec:authorize> <sec:authorize access="hasRole('ADMIN')"> Hello Admin. </sec:authorize>
如我們所見,我們可以使用此標籤根據訪問許可權或角色隱藏或顯示資訊部分。
hasRole(ADMIN) − 如果當前使用者具有 admin 角色,則評估結果為 true。
hasAnyRole(‘ADMIN’,’USER’) − 如果當前使用者具有任何列出的角色,則評估結果為 true
isAnonymous() − 如果當前使用者是匿名使用者,則評估結果為 true
isRememberMe() − 如果當前使用者是“記住我”使用者,則評估結果為 true
isFullyAuthenticated() − 如果使用者已透過身份驗證,並且既不是匿名使用者也不是“記住我”使用者,則評估結果為 true
如我們所見,access 屬性是指定 Web 安全表示式的屬性。然後,Spring Security 會評估該表示式。評估通常委託給 SecurityExpressionHandler<FilterInvocation>,該處理器在應用程式上下文中定義。如果它返回 true,則使用者可以訪問該部分中給出的資訊。
如果我們將 authorize 標籤與 Spring Security 的許可權評估器一起使用,我們還可以檢查使用者許可權,如下所示:
<p sec:authorize="hasPermission(#domain,'read') or hasPermission(#domain,'write')"> This content is visible to users who have read or write permission. </p>
我們還可以允許或限制使用者點選內容中的某些連結。
<a sec:authorize href="/admin"> This content will only be visible to users who are authorized to send requests to the "/admin" URL. </agt;
authentication 標籤
當我們想要訪問儲存在 Spring Security 上下文中的當前 Authentication 物件時,可以使用 authentication 標籤。然後,我們可以使用它直接在 JSP 頁面中呈現物件的屬性。例如,如果我們想在頁面中呈現 Authentication 物件的 principal 屬性,可以按如下方式進行:
<p sec:authentication="name" />
csrfInput 標籤
當啟用 CSRF 保護時,可以使用 csrfInput 標籤插入一個隱藏的表單欄位,其中包含 CSRF 保護令牌的正確值。如果未啟用 CSRF 保護,則此標籤不會輸出任何內容。
可以將該標籤與其他輸入欄位一起放置在 HTML <form></form> 塊中。但是,我們不能將該標籤放置在 <form:form></form:form> 塊中,因為 Spring Security 會自動在這些標籤中插入 CSRF 表單欄位,並且還會自動處理 Spring 表單。
<form method="post" action="/do/something"> <sec:csrfInput /> Username:<br /> <input type="text" username="username" /> ... </form>
csrfMetaTags 標籤
可以使用此標籤插入包含 CSRF 保護令牌表單欄位和標頭名稱以及 CSRF 保護令牌值的元標記。這些元標記可用於在應用程式的 Javascript 中使用 CSRF 保護。但是,此標籤僅在我們已在應用程式中啟用 CSRF 保護時才有效,否則,此標籤不會輸出任何內容。
<html> <head> <title>CSRF Protection in Javascript</title> <sec:csrfMetaTags /> <script type="text/javascript" language="javascript"> var csrfParam = $("meta[name='_csrf_param']").attr("content"); var csrfToken = $("meta[name='_csrf']").attr("content"); </script> </head> <body> ... </body> </html>
讓我們開始使用 Spring Security 進行實際程式設計。在開始使用 Spring 框架編寫示例之前,您必須確保已正確設定 Spring 環境,如 Spring Security - 環境設定 章節中所述。我們還假設您對 Spring Tool Suite IDE 有一定的瞭解。
現在讓我們繼續編寫一個基於 Spring MVC 的應用程式,該應用程式由 Maven 管理,它將要求使用者登入、對使用者進行身份驗證,然後提供使用 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>
Spring Security 配置類
在我們的 config 包中,我們建立了 WebSecurityConfig 類。我們將使用此類進行我們的安全配置,因此讓我們使用 @Configuration 註解和 @EnableWebSecurity 對其進行註釋。因此,Spring Security 知道將此類視為一個配置類。如我們所見,Spring 使應用程式配置變得非常容易。
WebSecurityConfig
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(); } }
控制器類
在此類中,我們為 "/" 端點、“/login”和“/admin”分別建立了索引頁面、登入頁面和此應用程式的管理頁面對映。
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"; } @GetMapping("/admin") public String admin() { return "admin"; } }
檢視
在 /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-springsecurity3"> <head> <title> Hello World! </title> </head> <body> <h1 th:inline="text">Hello World!</h1> <form th:action="@{/logout}" method="post"> <input type="submit" value="Sign Out"/> </form> </body> <html>
讓我們在 /src/main/resources/templates 資料夾中建立 login.html,其內容如下,作為登入頁面。我們使用預設名稱 username、password 和 remember-me 作為文字欄位。如果使用其他名稱,則需要在 Spring Security 配置類中設定相同的名稱。
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"> <h1>Please sign in</h1> <table> <tr> <td><label for="username"><b>Username</b></label></td> <td><input type="text" placeholder="Enter Username" name="username" id="username" required></td> </tr> <tr> <td><label for="password"><b>Password</b></label></td> <td><input type="password" placeholder="Enter Password" name="password" id="password" required></td> </tr> <tr> <td><label for="remember-me"><b>Remember Me</b></label> </td> <td><input type="checkbox" name="remember-me" /></td> </tr> <tr> <td> </td> <td><input type="submit" value="Sign In" /></td> </tr> </table> </form> </body> </html>
讓我們建立 admin.html 來使用 authorize 標籤。在這裡,我們添加了 <%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>。這將允許我們使用前面討論的 Spring Security 標籤庫。
admin.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 Admin! </title> </head> <body> <p>Admin Console</p> <h1 th:inline="text">Welcome <span sec:authentication="name"></span>!</h1> <p sec:authorize="hasRole('ADMIN')"> Control Panel </p> <a href="/logout" alt="logout">Sign Out</a> </body> <html>
如我們所見,我們在內容周圍添加了 authorize 標籤。此內容僅對我們的管理員使用者可見。任何其他訪問此頁面的使用者都將無法檢視此內容。另一個標籤 authentication 用於獲取 principal 以檢索已登入使用者的使用者名稱。
執行應用程式
一旦我們準備好所有元件,讓我們執行應用程式。右鍵單擊專案,選擇 Run As,然後選擇 Spring Boot App。
它將啟動應用程式,並且應用程式啟動後,我們可以執行 localhost:8080 以檢查更改。
輸出
現在開啟 localhost:8080,您可以看到我們的登入頁面。
輸入管理員詳細資訊的登入頁面

管理員頁面
當我們輸入管理員的有效憑據時,它將載入主頁。現在開啟 localhost:8080/admin。您可以看到管理員使用者可以看到“控制面板”文字。

輸入使用者詳細資訊的登入頁面
現在透過點選登出連結登出應用程式,然後使用使用者憑據登入。

使用者的管理員頁面
當我們輸入使用者的有效憑據時,它將載入主頁。現在載入 localhost:8080/admin 以開啟管理員頁面。您可以看到普通使用者看不到“控制面板”文字。
