表單登入
Spring Security 提供透過 HTML 表單提供使用者名稱和密碼的支援。本節詳細說明基於表單的身份驗證如何在 Spring Security 中運作。
本節探討基於表單的登入如何在 Spring Security 中運作。首先,我們看看使用者如何被重新導向到登入表單

前面的圖示建立在我們的 SecurityFilterChain
圖表之上。
首先,使用者向未經授權的資源 (
/private
) 發出未經身份驗證的請求。
Spring Security 的
AuthorizationFilter
指出未經身份驗證的請求被拒絕,並拋出 AccessDeniedException
。
由於使用者未經身份驗證,
ExceptionTranslationFilter
啟動開始身份驗證,並使用設定的 AuthenticationEntryPoint
將重新導向傳送到登入頁面。在大多數情況下,AuthenticationEntryPoint
是 LoginUrlAuthenticationEntryPoint
的實例。
瀏覽器請求重新導向到的登入頁面。
應用程式中的某些東西必須 呈現登入頁面。
當提交使用者名稱和密碼時,UsernamePasswordAuthenticationFilter
會驗證使用者名稱和密碼。UsernamePasswordAuthenticationFilter
擴展了 AbstractAuthenticationProcessingFilter,因此以下圖表看起來應該非常相似

該圖表建立在我們的 SecurityFilterChain
圖表之上。
當使用者提交其使用者名稱和密碼時,
UsernamePasswordAuthenticationFilter
會透過從 HttpServletRequest
實例中提取使用者名稱和密碼來建立 UsernamePasswordAuthenticationToken
,這是一種 Authentication
類型。
接下來,
UsernamePasswordAuthenticationToken
會傳遞到 AuthenticationManager
實例以進行身份驗證。AuthenticationManager
的外觀細節取決於 使用者資訊的儲存方式。
如果身份驗證失敗,則為失敗。
-
調用
RememberMeServices.loginFail
。如果未配置「記住我」功能,則此為空操作。請參閱 Javadoc 中的RememberMeServices
介面。 -
調用
AuthenticationFailureHandler
。請參閱 Javadoc 中的AuthenticationFailureHandler
類別
如果身份驗證成功,則為成功。
-
SessionAuthenticationStrategy
會收到新的登入通知。請參閱 Javadoc 中的SessionAuthenticationStrategy
介面。 -
Authentication 設定在 SecurityContextHolder 上。請參閱 Javadoc 中的
SecurityContextPersistenceFilter
類別。 -
調用
RememberMeServices.loginSuccess
。如果未配置「記住我」功能,則此為空操作。請參閱 Javadoc 中的RememberMeServices
介面。 -
ApplicationEventPublisher
發布InteractiveAuthenticationSuccessEvent
。 -
調用
AuthenticationSuccessHandler
。通常,這是一個SimpleUrlAuthenticationSuccessHandler
,它會重新導向到ExceptionTranslationFilter
在我們重新導向到登入頁面時儲存的請求。
預設情況下,Spring Security 表單登入已啟用。但是,一旦提供了任何基於 servlet 的設定,就必須明確提供基於表單的登入。以下範例顯示了一個最小的、明確的 Java 設定
-
Java
-
XML
-
Kotlin
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(withDefaults());
// ...
}
<http>
<!-- ... -->
<form-login />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
formLogin { }
}
// ...
}
在上述設定中,Spring Security 呈現預設登入頁面。大多數生產應用程式都需要自訂登入表單。
以下設定示範如何提供自訂登入表單。
-
Java
-
XML
-
Kotlin
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
// ...
}
<http>
<!-- ... -->
<intercept-url pattern="/login" access="permitAll" />
<form-login login-page="/login" />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
formLogin {
loginPage = "/login"
permitAll()
}
}
// ...
}
當在 Spring Security 設定中指定登入頁面時,您有責任呈現該頁面。以下 Thymeleaf 範本產生一個符合 /login
登入頁面的 HTML 登入表單。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Please Log In</title>
</head>
<body>
<h1>Please Log In</h1>
<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>
<input type="text" name="username" placeholder="Username"/>
</div>
<div>
<input type="password" name="password" placeholder="Password"/>
</div>
<input type="submit" value="Log in" />
</form>
</body>
</html>
關於預設 HTML 表單,有幾個重點
許多使用者不需要比自訂登入頁面做更多的事情。但是,如果需要,您可以自訂先前顯示的所有內容以及其他設定。
如果您使用 Spring MVC,則需要一個控制器,將 GET /login
對應到我們建立的登入範本。以下範例顯示了一個最小的 LoginController
-
Java
-
Kotlin
@Controller
class LoginController {
@GetMapping("/login")
String login() {
return "login";
}
}
@Controller
class LoginController {
@GetMapping("/login")
fun login(): String {
return "login"
}
}