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 緩存的工作原理,並解釋了我們不希望緩存安全資源的原因。我們還了解到,我們可以根據需要禁用或修改此行為。