Java 禁用Spring安全标头不起作用

Java 禁用Spring安全标头不起作用,java,security,caching,spring-security,spring-boot,Java,Security,Caching,Spring Security,Spring Boot,我需要在我的Spring安全配置中禁用缓存控制头 根据文档,一个简单的http.headers.disable() Cache-Control:no-cache, no-store, max-age=0, must-revalidate Expires:0 Pragma:no-cache 响应中的标题 我当前的安全配置是: http.antMatcher("/myPath/**") // "myPath" is of course not the real path .headers(

我需要在我的Spring安全配置中禁用缓存控制头

根据文档,一个简单的
http.headers.disable()

Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Expires:0
Pragma:no-cache
响应中的标题

我当前的安全配置是:

http.antMatcher("/myPath/**") // "myPath" is of course not the real path
    .headers().disable()
    .authorizeRequests()
     // ... abbreviated
    .anyRequest().authenticated();
到目前为止我尝试过的事情:

应用程序属性

我添加了
security.headers.cache=false
行,但这没有什么区别

使用过滤器

我尝试了以下过滤器:

@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);
      }
  });
}
添加日志记录后,我发现此筛选器只写入
X-XSS-Protection
头,所有缓存头都是稍后写入的,并且此筛选器无权“覆盖”它们。即使我在安全过滤器链的最后一个位置添加此过滤器,也会发生这种情况

使用拦截器

我尝试了以下拦截器:

@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", "");
}
这(完全可以预见)只是添加了头,这意味着原始的
no cache
头仍然会出现在拦截器添加的头之外


我在这里束手无策。如何摆脱Spring security设置的缓存控制头?

使用

http
.headers().disable()
...
将禁用您的标题。如果只希望禁用缓存控制,可以使用以下选项:

http
.headers()
.cacheControl().disable()
.及()
...
我已经发布了一篇文章来说明这一点

我猜您遇到的问题是您有多个
HttpSecurity
配置。请记住,如果您有:

http
.antMatchers(“/myPath/**”)
...
只有以
/myPath/
开头的URL才会受到影响。此外,如果您有多个
HttpSecurity
实例,则会按顺序考虑每个
HttpSecurity
实例,并且只使用第一个
HttpSecurity
实例。例如,如果您有:

@配置
@订单(1)
公共类MyPathAdminWebSecurity配置扩展了WebSecurity配置适配器{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
.antMatchers(“/myPath/admin/**”)
.授权请求()
.anyRequest().hasRole(“管理员”);
}
}
@配置
@订单(2)
公共类MyPathWebSecurity配置扩展了WebSecurity配置适配器{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
.antMatchers(“/myPath/**”)
.headers()
.cacheControl().disable();
}
}
@启用Web安全性
公共类WebSecurityConfig扩展了WebSecurityConfigureAdapter{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
.授权请求()
.anyRequest().authenticated();
}
}
如果您请求/myPath/admin/abc


首先考虑MyPathAdminWebSecurity配置。因为<代码> /MyPATT/ADMI/<代码>从<代码> /MyPrase/Admin/开始,我们将使用<代码> MyPaseAdmin WebSurfyCyfg,并且不考虑任何其他配置。这意味着您将期望获取此请求的头。

您需要一个类,该类使用两个overidden configure方法进行扩展,以配置筛选器和身份验证提供程序。例如,以下各项最低限度起作用:

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

}
您还可以对公共静态资源完全禁用Spring安全性,如下所示(在与上面相同的类中):

这需要配置两个资源处理程序以正确获取缓存控制头:

@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);
    }
}
这可能会有帮助:

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

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

因此,我自己找到了答案: 最后,我在我的yml配置文件中创建了一个名为
spring.resources.cachePeriod
的新条目,并将其设置为一个不同于
0
的值,从而使缓存控制头更改其值。糟糕的是,所有资源都使用这个设置,所以据我所知,没有办法根据资源的不同而有所不同


的答案帮助很大。

因此我遇到了一个类似的问题,希望我的大多数REST端点都具有Spring正在注入的标准“don't cache me”头,但在一个端点上我想插入自己的头

在您提供给ResponseEntry的HttpHeaders对象中指定您自己的对象不起作用

工作原理是直接在HttpServletResponse上显式设置头

Spring正在设置“缓存控制”、“Pragma”和“Expires”。下面演示如何覆盖和设置1分钟缓存:

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);
response.setHeader(“缓存控制”,“最大年龄=60”);
response.setHeader(“Pragma”,“Pragma”);
HttpHeaders=新的HttpHeaders();
headers.setExpires(System.currentTimeMillis()+60000);
返回新的ResponseEntity(正文、标题、HttpStatus.OK);

在我的应用程序类上通过
@enableAuth2sso
启用OpenId Connect后,我遇到了这个问题。经过大约六个小时的调试和文档阅读,结果证明必须将
@enableAuth2sso
放在
websecurityConfigureAdapter
上,否则自定义设置将被默认设置覆盖:

// 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();
    }
}
// In Application.java
@SpringBootApplication
@EnableOAuth2Sso  // <- Will overwrite config below
public class Application {
    //...
}

@Configuration
public class WebSecurity extends WebSecurityConfigurerAdapter {
    //...
}
//在Application.java中
@SpringBoot应用程序
公共类应用程序{
公共静态void main(字符串[]args){
SpringApplication.run(Application.class,args);
}
}
//在WebSecurity.java中
@配置

@enableAuth2sso//您的假设是错误的。对于已经存在的配置的子路径,我没有多个安全配置。我确实为其他路径配置了其他安全配置(与“/mypath”没有任何关系),但这些不应该真的是一个问题,我不需要禁用那里的头。感谢我一直在寻找的
defaultsDisabled()
。对我来说,由于你的问题,在添加
// In Application.java
@SpringBootApplication
@EnableOAuth2Sso  // <- Will overwrite config below
public class Application {
    //...
}

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