Рубрики
Без рубрики

Spring Security – Заголовки управления кэшем

Руководство по управлению заголовками управления кэшированием HTTP с помощью Spring Security.

Автор оригинала: baeldung.

1. введение

В этой статье мы рассмотрим, как мы можем контролировать кэширование HTTP с помощью Spring Security.

Мы продемонстрируем его поведение по умолчанию, а также объясним причины, лежащие в его основе. Затем мы рассмотрим способы изменить это поведение, частично или полностью.

2. Поведение Кэширования по умолчанию

Эффективно используя заголовки управления кэшем, мы можем проинструктировать ваш браузер кэшировать ресурсы и избегать сетевых переходов. Это уменьшает задержку, а также нагрузку на наш сервер.

По умолчанию Spring Security устанавливает для нас определенные значения заголовка управления кэшем, без необходимости что-либо настраивать.

Во-первых, давайте настроим Spring Security для нашего приложения:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {}
}

Мы переопределяем configure () , чтобы ничего не делать, это означает, что нам не нужно будет проходить аутентификацию, чтобы попасть в конечную точку, что позволит нам сосредоточиться на чисто тестовом кэшировании.

Далее, давайте реализуем простую конечную точку REST:

@GetMapping("/default/users/{name}")
public ResponseEntity getUserWithDefaultCaching(@PathVariable String name) {
    return ResponseEntity.ok(new UserDto(name));
}

Результирующий заголовок cache-control будет выглядеть следующим образом:

[cache-control: no-cache, no-store, max-age=0, must-revalidate]

Наконец, давайте реализуем тест, который попадает в конечную точку, и утвердим, какие заголовки отправляются в ответе:

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
  .header("Pragma", "no-cache");

По сути, это означает, что браузер никогда не будет кэшировать этот ответ.

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

3. Переопределение поведения кэширования по умолчанию

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

Для этого давайте попробуем переопределить заголовки элементов управления кэшем в одном методе обработчика с помощью элемента управления Cache cache. Класс CacheControl – это беглый конструктор, который позволяет нам легко создавать различные типы кэширования:

@GetMapping("/users/{name}")
public ResponseEntity getUser(@PathVariable String name) { 
    return ResponseEntity.ok()
      .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
      .body(new UserDto(name));
}

Давайте достигнем этой конечной точки в нашем тесте и утверждаем, что мы изменили заголовки:

given()
  .when()
  .get(getBaseUrl() + "/users/Michael")
  .then()
  .header("Cache-Control", "max-age=60");

Как мы видим, мы переопределили значения по умолчанию, и теперь наш ответ будет кэшироваться браузером в течение 60 секунд.

4. Отключение кэширования по умолчанию

Мы также можем полностью отключить заголовки управления кэшем по умолчанию в Spring Security. Это довольно рискованная вещь, и на самом деле не рекомендуется. Но, если мы действительно этого хотим, то мы можем попробовать это, переопределив метод configure в WebSecurityConfigurerAdapter:

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

Теперь давайте снова сделаем запрос к нашей конечной точке и посмотрим, какой ответ мы получим:

given()
  .when()
  .get(getBaseUrl() + "/default/users/Michael")
  .then()
  .headers(new HashMap());

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

5. Заключение

В этой статье показано, как Spring Security отключает кэширование HTTP по умолчанию, и объясняется, что это связано с тем, что мы не хотим кэшировать защищенные ресурсы. Мы также видели, как мы можем отключить или изменить это поведение по своему усмотрению.

Реализацию всех этих примеров и фрагментов кода можно найти в проекте GitHub – это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.