I need to disable the cache control headers in my Spring Security conf.
According to the documentation a simple http.headers.disable()
should do it, but I still see the
Cache-Control:no-cache, no-store, max-age=0, must-revalidate Expires:0 Pragma:no-cache
headers in responses.
My current security config is:
http.antMatcher("/myPath/**") // "myPath" is of course not the real path .headers().disable() .authorizeRequests() // ... abbreviated .anyRequest().authenticated();
Things I've tried so far:
application.properties
I added the security.headers.cache=false
line, but that made no difference.
Using a filter
I tried the following filter:
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) { @Override public void setHeader(String name, String value) { if (name.equalsIgnoreCase("Cache-Control")) { value = ""; } else if (name.equalsIgnoreCase("Expires")) { value = ""; } else if (name.equalsIgnoreCase("Pragma")) { value = ""; } super.setHeader(name, value); } }); }
After adding logging I saw that this filter only writes the X-XSS-Protection
header, all the cache headers are written somewhere later and this filter doesn't have access to "override" them. This happens even if I add this filter at the last position of the security filter chain.
Using an interceptor
I tried the following interceptor:
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { String requestUri = request.getRequestURI(); response.setHeader("Cache-Control", "max-age=3600"); response.setHeader("Expires", "3600"); response.setHeader("Pragma", ""); }
This (quite predictably) just added the headers, meaning that the original no-cache
headers still appear in addition to the ones added by the interceptor.
I'm at my wits end here. How do I get rid of the cache control header set by Spring security?
4 Answers
Answers 1
You’ll need a class that extends WebSecurityConfigurerAdapter with two overidden configure methods to configure the filter and the authentication provider. For example, the following works at a bare minimum:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @Configuration @EnableWebMvcSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class SecurityConfigDemo extends WebSecurityConfigurerAdapter { @Autowired private DemoAuthenticationProvider demoAuthenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { // Prevent the HTTP response header of "Pragma: no-cache". http.headers().cacheControl().disable(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(demoAuthenticationProvider); } }
You can also disabe Spring Security completely for public static resources as following (in the same class as above):
@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/static/public/**"); }
This requires configuring two resource handlers to get cache control headers right:
@Configuration public class MvcConfigurer extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // Resources without Spring Security. No cache control response headers. registry.addResourceHandler("/static/public/**") .addResourceLocations("classpath:/static/public/"); // Resources controlled by Spring Security, which // adds "Cache-Control: must-revalidate". registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/") .setCachePeriod(3600*24); } }
Answers 2
It may be help :
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // ... .headers() .defaultsDisabled() .cacheControl(); } }
Answers 3
So, I found the answer myself: I finally made the Cache-Control header to change its value by creating a new entry in my yml configuration file called spring.resources.cachePeriod
and set it to a value different than 0
. The bad thing is that all resources use this setting, so no way to make it different depending on the resource, as far as I know.
The answer to this question helped a lot.
Answers 4
You are right that using
http .headers().disable() ...
will disable your headers. If you only want cache control disabled, you can use the following:
http .headers() .cacheControl().disable() .and() ...
I have posted a sample that demonstrates this working along with a test.
My guess is the problem you are having is that you have multiple HttpSecurity
configurations. Remember that if you have:
http .antMatchers("/myPath/**") ...
Only URLs that start with /myPath/
will be impacted. Additionally, if you have multiple HttpSecurity
instances each HttpSecurity
instance is considered in order and only the first HttpSecurity
instance is used. For example if you have:
@Configuration @Order(1) public class MyPathAdminWebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .antMatchers("/myPath/admin/**") .authorizeRequests() .anyRequest().hasRole("ADMIN"); } } @Configuration @Order(2) public class MyPathWebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .antMatchers("/myPath/**") .headers() .cacheControl().disable(); } } @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated(); } }
If you request /myPath/admin/abc
First MyPathAdminWebSecurityConfig
is considered. Since /myPath/admin/
starts with /myPath/admin/
we will use MyPathAdminWebSecurityConfig
and not consider any other configuration. This means you will expect to get headers back for this request.
0 comments:
Post a Comment