Common Configurations

本節包含適用於所有或大多數 Spring Session 模組的常用設定。它包含以下使用案例的設定範例

變更 Session ID 的產生方式

預設情況下,Spring Session 使用 UuidSessionIdGenerator,而 UuidSessionIdGenerator 又使用 java.util.UUID 來產生 session ID。在某些情況下,加入其他字元以增加熵值可能會更好,或者您可能想要使用不同的演算法來產生 session ID。若要變更此設定,您可以提供自訂的 SessionIdGenerator bean

變更 Session ID 的產生方式
  • Java

@Bean
public SessionIdGenerator sessionIdGenerator() {
    return new MySessionIdGenerator();
}

class MySessionIdGenerator implements SessionIdGenerator {

    @Override
    public String generate() {
        // ...
    }

}

公開您的 SessionIdGenerator bean 後,Spring Session 將使用它來產生 session ID。

如果您是手動設定 SessionRepository bean (而不是使用 @EnableRedisHttpSession 等設定),您可以直接在 SessionRepository 實作上設定 SessionIdGenerator

直接在 SessionRepository 實作中設定 SessionIdGenerator
  • Java

@Bean
public RedisSessionRepository redisSessionRepository(RedisOperations redisOperations) {
    RedisSessionRepository repository = new RedisSessionRepository(redisOperations)
    repository.setSessionIdGenerator(new MySessionIdGenerator());
    return repository;
}

設定 Spring Session 後,您可以透過公開 CookieSerializer 作為 Spring bean 來客製化 session cookie 的寫入方式。Spring Session 隨附 DefaultCookieSerializer。當您使用 @EnableRedisHttpSession 等設定時,將 DefaultCookieSerializer 作為 Spring bean 公開會擴充現有的設定。以下範例示範如何自訂 Spring Session 的 cookie

	@Bean
	public CookieSerializer cookieSerializer() {
		DefaultCookieSerializer serializer = new DefaultCookieSerializer();
		serializer.setCookieName("JSESSIONID"); (1)
		serializer.setCookiePath("/"); (2)
		serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); (3)
		return serializer;
	}
1 我們將 cookie 的名稱自訂為 JSESSIONID
2 我們將 cookie 的路徑自訂為 / (而不是預設的 context root)。
3 我們將網域名稱模式 (regular expression) 自訂為 ^.?\\.(\\w\\.[a-z]+)$。這允許跨網域和應用程式共用 session。如果 regular expression 不符,則不會設定網域,並使用現有的網域。如果 regular expression 符合,則第一個群組會用作網域。這表示對 child.example.com 的請求會將網域設定為 example.com。但是,對 localhost:8080/192.168.1.100:8080/ 的請求會讓 cookie 保持未設定狀態,因此在開發中仍然有效,而無需對生產環境進行任何變更。
您應該只比對有效的網域字元,因為網域名稱會反映在回應中。這樣做可以防止惡意使用者執行 HTTP Response Splitting 等攻擊。

以下是可用的設定選項

  • cookieName: 要使用的 cookie 名稱。預設值:SESSION

  • useSecureCookie: 指定是否應使用安全 cookie。預設值:使用建立時 HttpServletRequest.isSecure() 的值。

  • cookiePath: cookie 的路徑。預設值:context root。

  • cookieMaxAge: 指定在建立 session 時要設定的 cookie 的最大存留時間。預設值:-1,表示在瀏覽器關閉時應移除 cookie。

  • jvmRoute: 指定要附加到 session ID 並包含在 cookie 中的字尾。用於識別要路由到哪個 JVM 以進行 session affinity。對於某些實作 (即 Redis),此選項沒有效能優勢。但是,它可以協助追蹤特定使用者的記錄。

  • domainName: 允許指定要用於 cookie 的特定網域名稱。此選項很容易理解,但通常需要在開發和生產環境之間進行不同的設定。請參閱 domainNamePattern 作為替代方案。

  • domainNamePattern: 用於從 HttpServletRequest#getServerName() 擷取網域名稱的不區分大小寫的模式。該模式應提供單一群組,用於擷取 cookie 網域的值。如果 regular expression 不符,則不會設定網域,並使用現有的網域。如果 regular expression 符合,則第一個群組會用作網域。

  • sameSite: SameSite cookie 指令的值。若要停用 SameSite cookie 指令的序列化,您可以將此值設定為 null。預設值:Lax

  • rememberMeRequestAttribute: 指示 remember-me 登入的請求屬性名稱。如果指定,cookie 將寫入為 Integer.MAX_VALUE

如果您使用 SpringSessionRememberMeServices 並且宣告了自訂的 DefaultCookieSerializer bean,則應設定 rememberMeRequestAttribute 欄位,以確保 Spring Session 依賴 session 到期時間而不是 cookie 到期時間。若要執行此操作,您可以使用以下程式碼片段:defaultCookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);

您可以透過公開 WebSessionIdResolver 作為 Spring bean,來自訂 WebFlux 應用程式中 session cookie 的寫入方式。Spring Session 預設使用 CookieWebSessionIdResolver。以下範例示範如何自訂 Spring Session 的 cookie

	@Bean
	public WebSessionIdResolver webSessionIdResolver() {
		CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
		resolver.setCookieName("JSESSIONID"); (1)
		resolver.addCookieInitializer((builder) -> builder.path("/")); (2)
		resolver.addCookieInitializer((builder) -> builder.sameSite("Strict")); (3)
		return resolver;
	}
1 我們將 cookie 的名稱自訂為 JSESSIONID
2 我們將 cookie 的路徑自訂為 / (而不是預設的 context root)。
3 我們將 SameSite cookie 指令自訂為 Strict

提供 Spring Session 的 ReactiveSessionRegistry 實作

Spring Session 提供與 Spring Security 的整合,以支援其反應式並行工作階段控制。這允許限制單一使用者可以同時擁有的活動工作階段數量,但是,與預設的 Spring Security 支援不同,這也適用於叢集環境。這是透過提供 Spring Security ReactiveSessionRegistry 介面的 SpringSessionBackedReactiveSessionRegistry 實作來完成。

將 SpringSessionBackedReactiveSessionRegistry 定義為 bean
  • Java

@Bean
public <S extends Session> SpringSessionBackedReactiveSessionRegistry<S> sessionRegistry(
        ReactiveSessionRepository<S> sessionRepository,
        ReactiveFindByIndexNameSessionRepository<S> indexedSessionRepository) {
    return new SpringSessionBackedReactiveSessionRegistry<>(sessionRepository, indexedSessionRepository);
}

請參閱 Spring Security 並行工作階段控制文件,以瞭解更多使用 ReactiveSessionRegistry 的方式。您也可以在此處查看範例應用程式 here