CORS
CORS란?
CORS(Cross-Origin Resource Sharing)는 웹 브라우저에서 동일 출처 정책(Same-Origin Policy)에 위배되는 리소스 요청을 허용하기 위한 보안 기능이다. 동일 출처 정책은 보안상의 이유로, 웹 페이지가 자신이 로드된 출처(origin)와 다른 출처의 자원에 접근하는 것을 기본적으로 제한한다. 이때 출처(origin)는 도메인, 프로토콜, 포트 번호로 구성된다.
예를 들어, http://example.com에서 로드된 웹 페이지는 기본적으로 http://another.com에서 호스팅된 API에 직접 요청을 보낼 수 없다. 이러한 제한이 해제되면 보안 취약점이 생길 수 있기 때문에, 이를 관리하기 위해 CORS가 필요하다.
요청 방식에 따른 CORS 여부
1. <img>, <video>, <script>, <link> 태그
태그를 통한 리소스는 기본적으로 Cross-Origin 정책을 지원한다.
- <link> 태그의 href 에서 다른 사이트의 .css 리소스에 접근하는 것이 가능
- <img> 태그의 src 에서 다른 사이트의 .png, .jpg 등의 리소스에 접근하는 것이 가능
- <script> 태그의 src 에서 다른 사이트의 .js 리소스에 접근하는 것이 가능
2. XMLHttpRequest, Fetch API 스크립트
기본적으로 Same-Origin 정책을 따른다.
- 다른 도메인의 소스에 대해 자바스크립트 ajax 요청 API 호출시
- 웹 폰트 CSS 파일 내 @font-face에서 다른 도메인의 폰트 사용 시
3. 요청에 따른 결과 차이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<img src="https://third-party-test.glitch.me/check.svg" alt="이미지">
<script>
fetch('https://third-party-test.glitch.me/check.svg')
.then(response => response.blob())
.then(imgBlob => {
const imageObjectURL = URL.createObjectURL(imgBlob); // 응답 받은 이미지를 blob 객체로 변환
const img = document.createElement('img'); // 이미지 태그를 생성하고
img.src = imageObjectURL; // 이미지 경로를 설정한뒤
document.body.append(img); // html에 추가
})
</script>
</body>
태그를 이용하여 요청한 경우에는 사진을 불러오지만 fetch api 스크립트를 이용한 요청은 CORS error
를 발생시킨다.
브라우저의 CORS 기본 동작
출처 구분은 서버가 하는 것이 아니라 브라우저에 구현된 스펙이다.
서버에서 리소스 요청은 해주었으나 브라우저가 응답의 출처를 분석하여 동일 출처가 아니면 에러를 뱉는다. 이 때문에 CORS 에러가 브라우저에서만 뜨고 서버에서는 정상적인 응답이 발생했다고 뜨는 것이다. 브라우저의 CORS 기본 동작은 다음과 같다.
- 클라이언트에서 HTTP 요청의 헤더에 Origin을 담아 전달
기본적으로 웹은 HTTP 프로토콜을 이용하여 서버에 요청을 보내는데, 이때 브라우저는 요청 헤더에 Origin 이라는 필드에 출처를 함께 담아 보내게 된다.
- 서버는 응답헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달
서버는 이 요청에 대한 응답을 할 때 응답 헤더에 Access-Control-Allow-Origin
이라는 필드를 추가하고 값으로 해당 리로스에 접근하는 것이 허용된 출처 url을 내려보낸다.
- 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교
응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보낸준 응답의 Access-Control-Allow-Origin을 비교하고 차단할지 말지를 결정한다.
결국 CORS 해결책은 서버가 Access-Control-Allow-Origin의 헤더에 허용할 출처를 기재해서 클라이언트에 응답하면 해결 할 수 있는 문제이다.(벡엔드 개발자가 고쳐야될 부분이라는 것이다.)
Spring Security에서 CORS error 해결
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
Spring에서 CORS error를 해결하기 위해서는 allowedOrigins
에 서버가 허용할 클라이언트 출처를 기재한다. allowedOrigins
는 서버가 특정 출처에서 온 요청을 허용할지를 결정하는 것이다. 위를 설정하면 Spring은 Access-Control-Allow-Origin
헤더를 통해 브라우저에게 “이 출처에서 온 요청은 허용된다”라고 알려주는 역할을 하게 된다.
참고 자료
https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F