知識庫 / Spring / Spring Security RSS 訂閱

Spring Security – 緩存控制頭

Spring Security
HongKong
6
02:41 PM · Dec 06 ,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 緩存。 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 的默認緩存控制頭。 這是一種相當冒險的做法,並不推薦這樣做。 但是,如果我們確實需要這樣做,我們可以嘗試通過創建 <em >SecurityFilterChain</em> bean 來實現:

@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.