1. 概述
本教程將演示如何使用 Spring Security 在 Web 應用程序中啓用和配置“記住我”功能。 設置具有安全性和簡單表單登錄的 MVC 應用程序,此前已經討論過。
該機制能夠 在多個會話中識別用户 – 因此,首先要理解的是“記住我”功能僅在會話超時後才會啓動。 默認情況下,這發生在不活動 30 分鐘後,但可以通過在 web.xml 中配置來更改超時時間。
注意:本教程側重於 標準基於 Cookie 的方法。 對於持久化方法,請參閲 Spring Security – Persistent Remember Me 指南。
2. 安全配置
讓我們看看如何使用 Java 設置安全配置:
@Configuration
@EnableWebSecurity
public class SecSecurityConfig {
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.build();
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withUsername("user1")
.password("{noop}user1Pass")
.authorities("ROLE_USER")
.build();
UserDetails admin = User.withUsername("admin1")
.password("{noop}admin1Pass")
.authorities("ROLE_ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth.requestMatchers("/anonymous*")
.anonymous()
.requestMatchers("/login*")
.permitAll()
.anyRequest()
.authenticated())
.formLogin(formLogin -> formLogin.loginPage("/login.html")
.loginProcessingUrl("/login")
.failureUrl("/login.html?error=true"))
.rememberMe(rememberMe -> rememberMe.key("uniqueAndSecret"))
.logout(logout -> logout.deleteCookies("JSESSIONID"));
return http.build();
}如您所見,使用 rememberMe() 方法進行基本配置極其簡單,同時通過額外的選項保持了極大的靈活性。 “key” 在這裏至關重要,它是整個應用程序的私有值,並且將在生成令牌的內容時使用。
此外,可以使用 tokenValiditySeconds() 配置令牌的有效時間,默認設置為 2 周,例如可以設置為 1 天。
rememberMe(rememberMe -> rememberMe.key("uniqueAndSecret").tokenValiditySeconds(86400))我們可以也可以查看等效的XML配置:
<http use-expressions="true">
<intercept-url pattern="/anonymous*" access="isAnonymous()" />
<intercept-url pattern="/login*" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login login-page='/login.html'
authentication-failure-url="/login.html?error=true" />
<logout delete-cookies="JSESSIONID" />
<remember-me key="uniqueAndSecret"/>
</http>
<authentication-manager id="authenticationManager">
<authentication-provider>
<user-service>
<user name="user1" password="{noop}user1Pass" authorities="ROLE_USER" />
<user name="admin1" password="{noop}admin1Pass" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>3. 登錄表單
登錄表單與我們用於表單登錄時使用的表單類似。
<html>
<head></head>
<body>
<h1>Login</h1>
<form name='f' action="login" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td>Remember Me:</td>
<td><input type="checkbox" name="remember-me" /></td>
</tr>
<tr>
<td><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
</form>
</body>
</html>請注意新增的複選框輸入 – 對應於 記住我。 此新增輸入足以啓用“記住我”選項進行登錄。
以下是更改默認路徑的方法:
.rememberMe().rememberMeParameter("remember-me-new")4. Cookie
該機制會在用户登錄時創建一個額外的 Cookie – “記住我” Cookie。
記住我 Cookie 包含以下數據:
- username – 用於標識已登錄的 principal
- expirationTime – 過期 Cookie;默認值為 2 周
- MD5 哈希 – 上述 2 個值(username 和 expirationTime)加上 password 和預定義的 key
這裏首先需要注意到的,username 和 password 都在 Cookie 中 – 這意味着如果其中任何一個發生更改,Cookie 將不再有效。 此外,username 可以從 Cookie 中讀取。
此外,如果“記住我” Cookie 被捕獲,則該機制可能存在漏洞。 Cookie 將在過期或憑據更改時仍然有效和可用。
5. 在實踐中
為了更直觀地觀察“記住我”機制的工作方式,您可以:
- 使用“記住我”選項登錄
- 等待會話過期(或在瀏覽器中刪除 JSESSIONID 餅乾)
- 刷新頁面
如果未啓用“記住我”選項,在餅乾過期後,用户應 被重定向回登錄頁面。 啓用“記住我”選項後,用户現在將 保持登錄狀態,藉助新的令牌/餅乾。
6. 結論
本教程演示瞭如何在安全配置中設置和配置“記住我”功能,並簡要介紹了進入 cookie 的數據類型。
當項目運行在本地時,可以通過 localhost 訪問 login.html。