# 스프링 시큐리티의 CSRF 보호가 작동하는 방식
- CSRF 공격은 사용자가 웹 애플리케이션에 로그인 했다고 가정하며 사용자는 공격자에게 속아서 작업중인 같은 애플리케이션에서 작업을 실행하는 스크립트가 포함된 페이지를 연다.
- 이 사용자는 이미 로그인을 했기 때문에 위조 코드는 이제 사용자를 가장하고 사용자 대신 작업을 수행할 수 있다.
- CSRF 보호의 시작점은 필터 체인의 CsrfFilter라는 한 필터다.
- CsrfFilter는 CsrfTokenRepository 구성 요소를 이용해 새 토큰 생성, 토큰 저장, 토큰 검증에 필요한 CSRF 토큰 값을 관리한다. 기본적으로 CsrfTokenRepository는 토큰을 Http 세션에 저장하고 랜덤 UUID로 토큰을 생성한다.
- 그림을 그리면 아래와 같다.
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new CsrfTokenLogger(), CsrfFilter.class)
.authorizeRequests().anyRequest().permitAll() ;
}
}
# CSRF 보호 맞춤 구성
- 스프링 시큐리티가 제공하는 CSRF 보호 솔루션은 두 가지가 있다.
- CSRF가 적용되는 경로 설정
- CSRF 토큰 관리 (DB에 CSRF 토큰 저장소를 두고 관리)
- 아래와 같이 구성하면, 특정 경로에만 CSRF가 적용될 수 있다.
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf(c-> {
c.ignoringAntMatchers("/ciao") ;
}) ;
http.authorizeRequests()
.anyRequest().permitAll() ;
}
}
# CORS(교차 출처 리소스 공유) 이용
- 서로 다른 출처 간에 통신을 허용과 관련된 정책
- Access-Control-Allow-Origin - 도메인의 리소스에 접근할 수 있는 외부 도메인을 지정한다.
- Access-Control-Allow-Methods - 다른 도메인에 대한 접근을 허용하지만, 특정 Http 방식만 지정하고 싶을 때 사용한다.
- Access-Control-Allow-Headers - 특정 요청에 이용할 수 있는 헤더에 제한을 추가한다.
# @CrossOrigin 어노테이션으로 CORS 정책 적용
- @CrossOrigin 어노테이션으로 다른 도메인에서의 요청을 허용하도록 CORS를 구성할 수 있다.
- 사용방법은 아래와 같다.
- @CrossOrigin은 @CrossOrigin({"example.com", "example.org"})와 같이 배열로 받을 수도 있다.
@PostMapping("/test")
@ResponseBody
@CrossOrigin("http://localhost:8080")
public String test() {
logger.info("Test Method called") ;
return "HELLO" ;
}
# CorsConfigurer로 CORS 적용
- 아래와 같이 간단한 설정으로 CORS를 설정할 수 있다.
- addMapping : CORS를 적용할 URL 패턴
- allowedOrigins : 자원 공유를 허락할 Origin을 지정
- allowedMethods : 허용할 HTTP method를 지정
- allowedHeaders : 허용할 headers를 설정
- credentials : 클라이언트 측에 대한 응답에 credentials(예: 쿠키, 인증 헤더)를 포함할 수 있는지 여부를 지정
- maxAge : 원하는 시간 만큼 예비 요청을 보내서 확인하는 것
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods(HttpMethod.GET.name()
, HttpMethod.POST.name()
, HttpMethod.PATCH.name()
, HttpMethod.PUT.name()
, HttpMethod.DELETE.name()
, HttpMethod.HEAD.name()
, HttpMethod.OPTIONS.name())
.maxAge(3600L)
.allowCredentials(false);
}
}