1. 소개
이 기사에서는 Spring Security로 HTTP 캐싱을 제어하는 방법을 살펴보겠습니다.
기본 동작을 시연하고 그 배경에 대한 이유도 설명합니다. 그런 다음 이 동작을 부분적으로 또는 완전히 변경하는 방법을 살펴보겠습니다.
2. 기본 캐싱 동작
캐시 제어 헤더를 효과적으로 사용하여 브라우저에 리소스를 캐시하고 네트워크 홉을 피하도록 지시할 수 있습니다. 이것은 대기 시간과 서버의 부하를 줄입니다.
기본적으로 Spring Security는 우리가 아무것도 구성할 필요 없이 특정 캐시 제어 헤더 값을 설정합니다.
먼저 애플리케이션에 Spring Security를 설정해 보겠습니다.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.build();
}
}
아무것도 하지 않도록 configure() 를 재정의하고 있습니다 . 즉, 엔드포인트에 도달하기 위해 인증할 필요가 없으므로 순전히 캐싱 테스트에 집중할 수 있습니다.
다음으로 간단한 REST 엔드포인트를 구현해 보겠습니다.
@GetMapping("/default/users/{name}")
public ResponseEntity<UserDto> getUserWithDefaultCaching(@PathVariable String name) {
return ResponseEntity.ok(new UserDto(name));
}
결과 캐시 제어 헤더는 다음과 같습니다.
[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. 기본 캐싱 동작 재정의
때때로 우리는 캐시되기를 원하는 리소스를 다룰 수 있습니다. 활성화하려면 리소스별로 수행하는 것이 가장 안전합니다. 이는 다른 리소스가 기본적으로 여전히 캐시되지 않음을 의미합니다.
이렇게 하려면 CacheControl 캐시를 사용하여 단일 처리기 메서드에서 캐시 제어 헤더를 재정의해 보겠습니다. CacheControl 클래스 는 유창한 빌더이므로 다양한 유형의 캐싱을 쉽게 만들 수 있습니다.
@GetMapping("/users/{name}")
public ResponseEntity<UserDto> 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의 기본 캐시 제어 헤더를 모두 끌 수도 있습니다. 이것은 매우 위험한 일이며 실제로 권장하지 않습니다. 하지만 정말로 원한다면 SecurityFilterChain 빈을 생성하여 시도할 수 있습니다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.headers().disable();
return http.build();
}
이제 엔드포인트에 다시 요청하고 어떤 응답을 받는지 살펴보겠습니다.
given()
.when()
.get(getBaseUrl() + "/default/users/Michael")
.then()
.headers(new HashMap<String, Object>());
보시다시피 캐시 헤더가 전혀 설정되지 않았습니다. 다시 말하지만 이것은 안전하지 않지만 원하는 경우 기본 헤더를 끄는 방법을 증명합니다.
5. 결론
이 기사에서는 Spring Security가 기본적으로 HTTP 캐싱을 비활성화하는 방법을 보여주고 이것이 Security 리소스를 캐싱하고 싶지 않기 때문이라고 설명합니다. 우리는 또한 우리가 적절하다고 생각하는 대로 이 동작을 비활성화하거나 수정할 수 있는 방법을 보았습니다.
이러한 모든 예제와 코드 스니펫의 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .