Disabling Spring Security headers does not work

时光怂恿深爱的人放手 提交于 2021-02-08 12:18:48

问题


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?


回答1:


It may be help :

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .defaultsDisabled()
        .cacheControl();
}
}

http://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html#headers-cache-control




回答2:


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);
    }
}



回答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.




回答4:


I had this issue after enabling OpenId Connect through @EnableOAuth2Sso on my application class. After about six hours of debugging and reading through docs, it turned out that @EnableOAuth2Sso MUST be placed on WebSecurityConfigurerAdapter or custom settings will be overridden by default settings:

Good

// In Application.java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

//In WebSecurity.java
@Configuration
@EnableOAuth2Sso  // <- This MUST be here, not above
public class WebSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().disable();
    }
}

Bad

// In Application.java
@SpringBootApplication
@EnableOAuth2Sso  // <- Will overwrite config below
public class Application {
    //...
}

@Configuration
public class WebSecurity extends WebSecurityConfigurerAdapter {
    //...
}



回答5:


So I had a similar problem, wanting most of my REST endpoints to have the standard "don't cache me" headers Spring is injecting, but on one endpoint I want to insert my own.

Specifying your own in the HttpHeaders object you give to the ResponseEntry does not work.

What DOES WORK is to explicitly set the headers DIRECTLY on the HttpServletResponse.

Spring is setting "Cache-Control", "Pragma" and "Expires". The following demonstrates how to override and set for a 1 minute caching:

response.setHeader("Cache-Control", "max-age=60");
response.setHeader("Pragma", "");
HttpHeaders headers = new HttpHeaders();
headers.setExpires(System.currentTimeMillis()+60000);
return new ResponseEntity<>(body, headers, HttpStatus.OK);



回答6:


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.



来源:https://stackoverflow.com/questions/36006029/disabling-spring-security-headers-does-not-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!