javascript
使用Spring Security在Spring Boot中进行缓存
在這篇文章中,我想分享一下O&B的一個團隊的經驗教訓。 他們正在使用帶有Spring Security的Spring Boot。
默認情況下,Spring Security保護的所有內容都將通過以下HTTP標頭發送到瀏覽器:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate本質上,響應將永遠不會被瀏覽器緩存。 盡管這似乎效率低下,但實際上有充分的理由要采用這種默認行為。 當一個用戶注銷時,我們不希望下一個登錄的用戶能夠看到前一個用戶的資源(如果緩存了,則可以這樣做)。
默認情況下不緩存任何內容,并保留顯式啟用緩存是有意義的。 但是,如果不緩存任何內容,則不好,因為這會導致高帶寬使用和緩慢的頁面加載。
很好的是,在Spring Boot中啟用靜態內容緩存非常容易(即使使用Spring Security也是如此)。 只需配置一個緩存周期。 就是這樣!
# Boot 2.x spring.resources.cache.cachecontrol.max-age=14400# Boot 1.x spring.resources.cache-period=14400但是有一些陷阱! 對于某些版本,它不是那么簡單! 讓我進一步解釋。
有幾種方法可以返回內容:
啟用靜態內容緩存
第一個(提供靜態內容)是通過配置所述屬性(通常在如上所述的application.properties中)來處理的。
通過HttpServletResponse設置
在第二種情況下,控制器處理程序方法可以選擇通過HttpServletResponse方法參數設置“ Cache-Control”標頭。
@Controller ... class ... {@RequestMapping(...)public String ...(..., HttpServletResponse response) {response.setHeader("Cache-Control", "max-age=14400");return ...; // view name} }只要Spring Security不會覆蓋它,它就可以工作。
通過HttpEntity / ResponseEntity設置
在第三種情況下,控制器處理程序方法可以選擇設置返回的HTTP實體的“ Cache-Control”標頭。
@Controller ... class ... {@RequestMapping(...)public ResponseEntity<...> ...(...) {return ResponseEntity.ok().cacheControl(...).body(...);} }只要Spring Security還沒有編寫自己的“ Cache-Control”頭文件,它就可以工作。
引擎蓋下
引擎蓋下
要了解其工作時間和原因,以下是相關序列。
對于Spring Security Web 4.0.x,4.2.0和4.2.4及更高版本,將發生以下順序:
- 在HttpServletResponse明確設置標頭。
- 或者,設置在返回的報頭HttpEntity或ResponseEntity (參照handleReturnValue()的方法HttpEntityMethodProcessor )。
- 請注意,如果HttpEntityMethodProcessor 還不存在 , HttpEntityMethodProcessor僅將頭(來自HttpEntity )寫入實際響應。 這是一個問題,因為早在#1中,標頭已經設置好了。
- 但是,在Spring Web MVC 4.2.5中, WebContentGenerator僅在不存在時才寫入“ Cache-Control”標頭! 。 這是一個問題,因為早在#1中,標頭已經設置好了。
- 在Spring Web MVC 4.2.6及更高版本中,即使它已經存在,它也會添加“ Cache-Control”標頭。 因此,即使已在#1中設置了標頭也沒有問題。
使用Spring Security Web 4.1.x,4.2.5和更高版本(在Spring Boot 1.5.11中使用版本4.2.5),順序已更改。 它是這樣的:
- 在HttpServletResponse明確設置標頭。
- 或者,設置在返回的報頭HttpEntity或ResponseEntity (參照handleReturnValue()的方法HttpEntityMethodProcessor )。
- 請注意,如果HttpEntityMethodProcessor 還不存在 , HttpEntityMethodProcessor僅將頭(來自HttpEntity )寫入實際響應。 沒問題,因為尚未設置標題。
- 沒問題,因為如果已經設置了緩存頭,它將不會覆蓋。
工作版本
以上三種控制緩存的情況都在Spring Boot 1.5.11和Spring Boot 2.x中起作用。 但是,如果無法升級到那些版本,請參見以下類,并檢查它是否具有您想要的行為(使用上述順序):
- HeaderWriterFilter (請參閱doFilterInternal方法)
- CacheControlHeadersWriter (請參閱writeHeaders()方法)
- WebContentGenerator (請參閱applyCacheControl()方法)
- HttpEntityMethodProcessor (請參見handleReturnValue()方法)
另外,請注意,Spring Security Web 4.2.5及更高版本將寫入以下HTTP標頭(即使已設置它們,也將其覆蓋,例如,在控制器中):
- 通過XContentTypeOptionsHeaderWriter X-Content-Type-Options
- 通過HstsHeaderWriter Strict-Transport-Security HstsHeaderWriter
- 通過XFrameOptionsHeaderWriter X-Frame-Options
- 通過XXssProtectionHeaderWriter X-XSS-Protection
這是因為,與CacheControlHeadersWriter不同,上述內容的標頭編寫器不會檢查標頭是否已經存在。 他們只需設置各自的HTTP標頭即可。 請參考各自的標題編寫器類,并發布#5193 。
另一種選擇是讓Spring Security忽略靜態資源請求。 這樣,配置的緩存周期將不會被覆蓋。
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/css/**", "/js/**");// If the above paths are served by the// Spring Boot auto-configured// static resource request handler,// and a cache period is specified,// then it will have a "Cache-Control"// HTTP header in its response.// And it would NOT get overwritten by Spring Security.} }目前為止就這樣了。 希望這可以清除一切。
翻譯自: https://www.javacodegeeks.com/2018/07/caching-spring-boot-spring-security.html
總結
以上是生活随笔為你收集整理的使用Spring Security在Spring Boot中进行缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓点菜软件(安卓点菜)
- 下一篇: 使用Spring Boot,JHipst