브라우저는 보안상의 이유로 다른 출처의 리소스를 사용하는 것을 기본적으로 제한하고 있다.
다른 출처의 리소스를 불러오려면 접근할 수 있는 권한을 달라고 브라우저에게 요청을 해야한다.
이번 프로젝트 중 프론트엔드 서버에서 백엔드 서버에 접근하니 아래와 같은 요청이 떴다.
CORS 정책에 의해서 다른 출처의 서버에 접속하는 것이 막혔다고 브라우저에서 에러를 발생시켜준 것이다.
권한 요청을 Http header에 담아보내 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주어야 한다.
백엔드에서 몇 가지 설정이 필요했다.
이번 프로젝트에서 Spring Security + JWT 를 사용했기 때문에 Client는 API 호출 시 모든 요청에 대해 Header의 Authorization에 JWT 토큰을 전송한다.
그래서 일반적인 요청이 아니라 브라우저에서 서버에 preflighted 요청을 보낸다.
* preflighted 요청
1. options 메서드를 통해 다른 도메인의 리소스에 요청이 가능한지 확인한다.
2. 요청이 가능하다면 실제 요청을 보낸다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// http formLogin, headers .. 설정
http.cors();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
- http.cors()
- Spring이 제공하는 CorsFilter를 등록하는 것과 같다.
- 아래 코드와 같이 CorsConfig 만든 다음 filter를 추가하는 방법도 있다.
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", config); return new CorsFilter(source); }
- addAllowedOrigin("*")
*로 해놓으면 모든 주소 허용한다는 의미이다. 나중에 프론트엔드 서버 ip 주소만 허용하도록 변경했다.
- addAllowedHeader("*")
허용되는 HTTP request headers 지정.
- addAllowedMethod("*")
허용하는 Method. *로 해놓으면 모든 method 허용한다는 의미.
- setAllowCredentials(true)
서버가 응답할 때 json을 자바스크립트에서 처리할 수 있도록 한다.
- config.addExposedHeader("Authorization")
token이 response로 노출되어야 하기 때문에 나열해주기.
Authorization은 와일드 카드로 지정하지 않으므로 꼭 명시해줘야 한다.
'개발 > Project' 카테고리의 다른 글
JPA N+1 문제 성능 최적화하기(1) (1) | 2023.01.19 |
---|---|
도메인 객체지향적으로 Refactoring 하기 (0) | 2022.02.13 |
JPA N+1 문제 해결 후 성능 비교해보기(2) (0) | 2022.02.07 |
[springBoot] test용 h2 DB 설정하기 (0) | 2022.01.24 |