知識庫 / Spring / Spring Security RSS 訂閱

Spring Security – 持續會話保持功能

Spring Security
HongKong
6
03:02 PM · Dec 06 ,2025

1. 概述

本文將演示如何在 Spring Security 中設置 記住我功能 – 不僅使用標準 Cookie 方式,而是 採用更安全的解決方案,使用持久化

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

2. 兩種“記住我”解決方案Spring 提供了兩種略有不同的實現方案來解決這個問題。它們都使用 UsernamePasswordAuthenticationFilter,通過鈎子來調用 RememberMeServices 實現。

我們之前已經介紹了標準“記住我”解決方案,它僅使用一個 cookie,即 remember-me cookie,其中包含用户名、過期時間以及包含密碼的 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. The Spring Security Configuration

The first key configuration is the Remember-Me Http Configuration (notice the dataSource property):

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

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

<!-- Persistent Remember Me Service -->
<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>
 
<!-- Uses a database table to maintain a set of persistent login data -->
<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>

<!-- Authentication Manager (uses same UserDetailsService as RememberMeService)--> 
<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="myUserDetailsService"/> 
    </authentication-provider> 
</authentication-manager> 

5. Cookie

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

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

此係列和令牌的組合被持久保存,使得暴力破解攻擊的可能性極低。

6. 在實踐中

要觀察“記住我”機制在瀏覽器中的工作,您可以:

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

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

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

7. 結論

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

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

發佈 評論

Some HTML is okay.