Spring Security – 緩存控制頭

Spring Security
Remote
1
09:57 PM · Nov 29 ,2025

1. 簡介

在本文中,我們將探討如何使用 Spring Security 控制 HTTP 緩存。

我們將演示其默認行為,並解釋其背後的原因。然後,我們將研究如何更改此行為,方法是部分或完全更改。

2. 默認緩存行為

通過有效地使用緩存控制標頭,我們可以指示瀏覽器緩存資源並避免網絡跳轉。這降低了延遲,同時也減輕了服務器的負載。

默認情況下,Spring Security 為我們設置了特定的緩存控制標頭值,而無需我們進行任何配置。

首先,讓我們為我們的應用程序設置 Spring Security:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http.build();
    }
}

我們通過覆蓋 configure() 來不做任何操作,這意味着我們不需要進行身份驗證才能命中端點,使我們能夠專注於純粹的緩存測試。

接下來,讓我們實現一個簡單的 REST 端點:

@GetMapping("/default/users/{name}")
public ResponseEntity<UserDto> getUserWithDefaultCaching(@PathVariable String name) {
    return ResponseEntity.ok(new UserDto(name));
}

生成的 cache-control 標頭將如下所示:

[cache-control: no-cache, no-store, max-age=0, must-revalidate]

最後,讓我們實現一個測試,該測試命中端點,並斷言響應中發送的標頭:

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
  .header("Pragma", "no-cache")

本質上,這意味着瀏覽器永遠不會緩存此響應。

雖然這看起來效率低下,但實際上有充分的理由支持這種默認行為——如果一個用户註銷,另一個用户登錄,我們不想讓他們能夠看到前一個用户的資源。默認情況下不緩存任何內容,並留給我們自行啓用緩存,更安全。

3. 覆蓋默認緩存行為

有時我們可能需要處理需要緩存的資源。如果我們要啓用它,最好以按資源為基礎的方式進行,這意味着其他資源將默認情況下不會被緩存。

要做到這一點,讓我們嘗試通過使用 CacheControl 緩存處理器,從而覆蓋緩存控制標頭。

@GetMapping("/users/{name}")
public ResponseEntity<UserDto> getUser(@PathVariable String name) { 
    return ResponseEntity.ok()
      .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
      .body(new UserDto(name));
}

讓我們在我們的測試中命中此端點,並斷言我們已更改標頭:

given()
  .when()
  .get(getBaseUrl() + "/users/Michael")
  .then()
  .header("Cache-Control", "max-age=60");

正如我們所看到的,我們已覆蓋了默認值,並且現在我們的響應將在瀏覽器中緩存 60 秒。

4. 關閉默認緩存行為

我們也可以完全關閉 Spring Security 的默認緩存控制頭。 這是一件相當冒險的事情,並不推薦這樣做。 但是,如果我們真的想這樣做,我們可以嘗試通過創建 SecurityFilterChain 豆來完成:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.headers().disable();
    return http.build();
}

現在,讓我們再次向我們的端點發送請求,看看我們得到什麼響應:

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .headers(new HashMap<String, Object>());

正如我們所看到的,根本沒有設置任何緩存頭。 再次強調,這不安全,但證明了如果我們想這樣做,我們如何關閉默認頭。

5. 結論

本文介紹了 Spring Security 默認情況下禁用 HTTP 緩存的工作原理,並解釋了我們不希望緩存安全資源的原因。我們還了解到,我們可以根據需要禁用或修改此行為。

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

發佈 評論

Some HTML is okay.