Spring Security – 持續會話記住我

Spring Security
Remote
0
06:52 PM · Nov 29 ,2025

1. 概述

本文將介紹如何設置 Spring Security 中的 記住我功能 – 不僅使用標準 cookie 方式,還 採用更安全的方法,使用持久化

作為快速介紹 – Spring 可以配置為在瀏覽器會話之間記住登錄憑據。這允許您登錄到網站,然後在訪問該網站時自動為您登錄(即使在您關閉瀏覽器期間)。

2. 兩種“記住我”解決方案

Spring 提供兩種略有不同的實現來解決這個問題。兩者都使用 UsernamePasswordAuthenticationFilter,通過鈎子調用 RememberMeServices 實現。

我們之前已經介紹了標準“記住我”解決方案,它僅使用一個 cookie,在之前的文章中,這個 cookie 叫做 remember-me,包含用户名、過期時間以及包含密碼的 MD5 哈希值。由於它包含密碼的哈希值,該解決方案在 cookie 被捕獲時可能存在漏洞

考慮到這一點,讓我們來查看第二個方法,使用 PersistentTokenBasedRememberMeServices 在會話之間將持久登錄信息存儲在數據庫表中。

3. 前提條件 – 創建數據庫表

首先,我們需要在數據庫中擁有登錄信息——我們需要創建一個表來存儲數據:

create table if not exists persistent_logins ( 
  username varchar_ignorecase(100) not null, 
  series varchar(64) primary key, 
  token varchar(64) not null, 
  last_used timestamp not null 
);

這將在啓動時自動創建,通過以下 XML 配置(使用內存中的 H2 數據庫):


<!-- create H2 embedded database table on startup -->
<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:/persisted_logins_create_table.sql"/> 
</jdbc:embedded-database>

為了完整性,這裏是持久化設置的方式:


@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
public class DatabaseConfig {

    @Autowired private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.user"));
        dataSource.setPassword(env.getProperty("jdbc.pass"));
        return dataSource;
    }
}

4. Spring Security 配置

第一個關鍵配置是 Remember-Me Http 配置(注意 dataSource 屬性):

<http use-expressions="true">
    ...
    <remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
<http"> 

接下來,我們需要配置實際的 RememberMeServiceJdbcTokenRepository (它也使用了 dataSource):

<!-- 永久 Remember Me 服務 -->
<beans:bean id="rememberMeAuthenticationProvider" class=
  "org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:constructor-arg value="myAppKey" />
    <beans:constructor-arg ref="jdbcTokenRepository" />
    <beans:constructor-arg ref="myUserDetailsService" />
</beans:bean>
 
<!-- 使用數據庫表來維護一組持久登錄數據 -->
<beans:bean id="jdbcTokenRepository" 
  class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl"> 
    <beans:property name="createTableOnStartup" value="false" /> 
    <beans:property name="dataSource" ref="dataSource" /> 
</beans:bean>

<!-- 身份驗證管理器 (使用與 RememberMeService相同的 UserDetailsService)--> 
<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="myUserDetailsService"/> 
    </authentication-provider> 
</authentication-manager> 

5. Cookie

如我們所説,標準 TokenBasedRememberMeServices 在 Cookie 中存儲了哈希後的用户密碼。

這個解決方案——PersistentTokenBasedRememberMeServices 使用一個 唯一的系列標識符用於用户。該標識符識別用户的初始登錄,並且在用户在持久會話期間自動登錄時保持不變。它還包含 一個隨機令牌,該令牌在用户通過持久的記住我功能登錄時會重新生成。

這種隨機系列和令牌的組合被持久化,使得暴力破解攻擊非常不可能。

6. 在實踐中

要查看記住我機制在瀏覽器中的工作,您可以:

  1. 使用記住我功能登錄
  2. 關閉瀏覽器
  3. 重新打開瀏覽器並返回同一頁面。刷新。
  4. 您仍然會登錄

未啓用記住我,當 cookie 過期時,用户應被重定向回登錄頁面。啓用記住我,用户現在藉助新的 token/cookie 保持登錄狀態。

您還可以查看瀏覽器中的 cookie,以及在數據庫中的持久化數據(請注意,您可能需要從嵌入式 H2 實現中切換)。

7. 結論

本教程演示瞭如何設置和配置數據庫持久化的“記住我”令牌功能。它也是對先前文章的補充,該文章討論了基於標準 Cookie 令牌的功能。數據庫方法更安全,因為密碼詳情不會保存在 Cookie 中——但它也需要稍微更多的配置。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.