Отключение Spring Заголовки безопасности не работают

Мне нужно отключить заголовки управления кэшем в моем Spring безопасности conf.

В соответствии с документацией простой 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();

Вещи, которые я пробовал до сих пор:

application.properties

Я добавил строку 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 безопасности?

Ответ 2

Вам понадобится класс, который расширяет WebSecurityConfigurerAdapter с помощью двух переопределенных методов настройки для настройки фильтра и поставщика проверки подлинности. Например, нижеследующее работает на минимальном уровне:

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 Безопасность для общедоступных статических ресурсов следующим образом (в том же классе, что и выше):

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/static/public/**");
}

Для этого необходимо настроить два обработчика ресурсов, чтобы получить правильные заголовки кеша:

@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

Итак, я сам нашел ответ: Я, наконец, сделал заголовок Cache-Control, чтобы изменить его значение, создав новую запись в моем файле конфигурации yml с именем spring.resources.cachePeriod и установив его в значение, отличное от 0. Плохо то, что все ресурсы используют эту настройку, так что, насколько мне известно, нет никакого способа сделать ее другой в зависимости от ресурса.

Ответ на этот вопрос помог многим.

Ответ 4

Итак, у меня была аналогичная проблема, так как большинство моих конечных точек REST имели стандартные "не кэшировать меня" заголовки Spring, но в одной конечной точке я хочу вставить свой собственный.

Указание вашего собственного объекта HttpHeaders, который вы передаете ResponseEntry, не работает.

ЧТО РАБОТАЕТ, чтобы явно установить заголовки DIRECTLY на HttpServletResponse.

Spring устанавливает "Cache-Control", "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);

Ответ 5

У меня была эта проблема после включения OpenId Connect через @EnableOAuth2Sso в моем классе приложения. Примерно через шесть часов после отладки и чтения через документы оказалось, что @EnableOAuth2Sso ДОЛЖЕН быть размещен на WebSecurityConfigurerAdapter, или пользовательские настройки будут переопределены по умолчанию:

Хорошо

// 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 {
    //...
}

Ответ 6

В весенней загрузке есть много способов для http-кэширования. Использование пружинного башмака 2.1.1 и дополнительно пружинной безопасности 5.1.1.

1. Для ресурсов, использующих обработчик ресурсов в коде:

Таким способом вы можете добавлять индивидуальные расширения ресурсов.

registry.addResourceHandler

Для добавления пути URI, где получить ресурс

.addResourceLocations

Предназначен для установки местоположения в файловой системе, где расположены ресурсы (данное значение является относительным с classpath, но также возможен абсолютный путь с file :://.)

.setCacheControl

Предназначен для настройки заголовков кэша (не требует пояснений).

Resourcechain и resolver не являются обязательными (в данном случае они соответствуют значениям по умолчанию).

@Configuration
public class CustomWebMVCConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/*.js", "/*.css", "/*.ttf", "/*.woff", "/*.woff2", "/*.eot",
            "/*.svg")
            .addResourceLocations("classpath:/static/")
            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)
                    .cachePrivate()
                    .mustRevalidate())
            .resourceChain(true)
            .addResolver(new PathResourceResolver());
    }
}

2. Для ресурсов, использующих файл конфигурации свойств приложения

То же самое, что и выше, за исключением конкретных шаблонов, но теперь как config. Эта конфигурация применяется ко всем ресурсам в перечисленных статических местоположениях.

#spring.resources.cache.cachecontrol.cache-private=true
#spring.resources.cache.cachecontrol.must-revalidate=true
#spring.resources.cache.cachecontrol.max-age=31536000
#spring.resources.static-locations=classpath:/static/

3. На уровне контроллера

Ответом здесь является HttpServletResponse, введенный в метод контроллера в качестве параметра.

no-cache, must-revalidate, private

getHeaderValue выведет параметры кэша в виде строки. например

response.setHeader(HttpHeaders.CACHE_CONTROL,
            CacheControl.noCache()
                    .cachePrivate()
                    .mustRevalidate()
                    .getHeaderValue());

Ответ 7

Вы правы, что используя

http
    .headers().disable()
    ...

отключит ваши заголовки. Если вы хотите, чтобы управление кэшем отключено, вы можете использовать следующее:

http
    .headers()
        .cacheControl().disable()
        .and()
    ...

Я разместил образец, который демонстрирует это, работая по с тестом.

Моя догадка заключается в том, что у вас есть несколько конфигураций HttpSecurity. Помните, что если у вас есть:

http
    .antMatchers("/myPath/**")
    ...

Будут затронуты только URL-адреса, начинающиеся с /myPath/. Кроме того, если у вас несколько экземпляров HttpSecurity, каждый экземпляр HttpSecurity рассматривается в порядке и используется только первый экземпляр HttpSecurity. Например, если у вас есть:

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

Если вы запрашиваете /myPath/admin/abc

Рассматривается первая MyPathAdminWebSecurityConfig. Поскольку /myPath/admin/ начинается с /myPath/admin/, мы будем использовать MyPathAdminWebSecurityConfig и не будем рассматривать любую другую конфигурацию. Это означает, что вы ожидаете получить заголовки для этого запроса.