CORS(Cross-Origin Resource Sharing) 란
웹 애플리케이션에서 다른 출처(origin)의 리소스에 접근할 수 있는 규칙을 정의하는 메커니즘입니다.
웹 브라우저는 보안 상의 이유로 스크립트가 동일한 출처에서 실행될 때만 리소스에 접근을 허용합니다. 그러나 이로 인해 다른 출처의 리소스에 접근하는 요청이 차단되는 문제가 발생할 수 있습니다. 이를 해결하기 위해 CORS가 도입되었습니다.
개발하면서 마주치는 CORS 에러 분석하기
Warning! Access to fetch at ‘https://myhompage.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
'https://myhomepage.com'에서 'https://localhost:3000' 출처로 가져올 수 있는 액세스가 CORS 정책에 의해 차단되었습니다. 요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. 불투명한 응답이 필요에 적합한 경우, 요청 모드를 'no-cors'로 설정하여 CORS가 비활성화된 리소스를 가져오십시오.
CORS는 웹 서버가 리소스에 대한 액세스를 허용할지 여부를 결정하도록 브라우저에게 알려주는 HTTP 헤더를 사용합니다. 서버는 헤더를 포함하여 브라우저에 응답하고, 브라우저는 이 헤더를 확인하여 요청이 허용되는지 여부를 결정합니다.
출처 (Origin)이란 무엇인가
간단히, Origin은 Protocol + Hostname + Port를 합친 URL을 의미합니다.
ex) https://myshop.com:8080 이라 할 수 있습니다.
SOP (Same-Origin-Policy) 동일 출처 정책 이해하기
SOP 정책은 단어 그대로 동일한 출처에 대한 정책을 의미하며, 동일한 출처에서만 리소르를 공유할 수 있음을 의미합니다.
즉, 동일한 출처 서버에 있는 리소스는 자유롭게 통신하여 사용할 수 있지만, 다른 출처 (protocol, hostname, port가 다른) 서버에 있는 리소스는 서로 주고받을 수 없습니다.
동일 출처 정책이 필요한 이유
동일 출처가 아닌 경우 접근을 차단하는 이유는
출처가 다른 두 어플리케이션이 자유로이 소통할 수 있는 환경은 위험한 환경이라 할 수 있습니다. 만일 제약이 없다면, 해커가 CSRF(Cross-Site Request Forgery)나 XSS(Cross-Site Scripting) 등의 방법을 이용해서 우리가 만든 애플리케이션에서 해커가 심어놓은 코드가 실행하여 개인 정보를 가로챌 수 있습니다.
출처 비교와 차단은 브라우저가 한다
개발자들이 착각하는 부분이 위의 출처 구분을 서버가 하는 것으로 오해하는 것이다. 서버에 요청을 했는데 무언가 에러가 뜨면 서버가 문제라고 생각이 들 수 있지만, 출처를 비교하는 로직은 서버에 구현된 스펙이 아닌 브라우저에 구현된 스펙입니다.
하지만 인터넷은 여러 사람들에게 오픈된 환경이고, 개발을 진행하면서 Port 번호가 다른 환경에서 개발을 진행할 것이다.
이런 환경에서 웹페이지에서 다른 출처에 있는 리소스를 가져와 사용하는 일은 매우 흔한 일이라 모든 출처를 막을 수는 없습니다.
그래서 몇 가지 예외 조항을 두고 다른 출처의 리소스 요청이라도 이 조항에 해당할 경우에는 허용하기로 했는데,
그 중 하나가 바로 CORS 정책을 지킨 리소스 요청입니다.
일반적으로 CORS 정책은 다음과 같은 상황에서 적용됩니다:
- 서로 다른 도메인, 포트, 프로토콜로부터 리소스에 접근하는 경우
- XMLHttpRequest나 Fetch API를 사용하여 AJAX 요청을 보내는 경우
- 웹 폰트, 스타일시트, 이미지 등 외부 리소스에 접근하는 경우
CORS는 보안을 강화하기 위해 중요한 역할을 합니다.
브라우저의 CORS 기본 동작 살펴보기
1. 클라이언트에서 HTTP요청의 헤더에 Origin을 담아 전달합니다.
기본적으로 웹은 HTTP 프로토콜을 이용하여 서버에 요청을 보내게 되는데, 이때 브라우저는 요청 헤더에 Origin이라는 필드에 출처를 함께 담아 보내게 됩니다.
2. 서버는 응답헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달한다.
이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더에 Access-Control-Allow-Origin 이라는 필드를 추가하고,
값으로 '이 리소스를 접근하는 것이 허용된 출처 url'을 내려보낸다.
3. 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교한다.
이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해 본 후 차단할지 말지를 결정합니다.
만약 유효하지 않다면 그 응답을 사용하지 않고 버립니다. (CORS 에러 !!)
Spring에서 전역적으로 CORS를 설정하기
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedHeaders("*")
.allowedOrigins("*")
.allowCredentials(true);
.allowedMethods("*");
}
}
- allowedOrigins : 허용할 출처를 작성합니다. ex) http://localhost:8080, http://localhost:3000
- allowedMethods : 허용할 HTTP 메서드 방식 설정 ex) GET, POST, DELETE...
- allowedHeaders : 허용할 Header 작성
- allowdCredentials : 쿠키 인증 요청 설정
'Spring Framework > Spring' 카테고리의 다른 글
[Spring Cloud] Spring Config Server를 이용해 설정 파일 관리하기 (0) | 2024.04.01 |
---|---|
[Spring Cloud] Eureka Server, Discovery Service 이해하기 (0) | 2024.03.31 |
[SPRING] Spring 객체지향 설계 solid 원칙 이해하기 - Spring Container, IoC, DI (1) | 2024.02.07 |
[Spring] 스프링 파일, 이미지 업로드 / 인스타 이미지 업로드 및 해시태그 파싱하기 - MultipartFile, File (0) | 2023.12.21 |
[Spring] 스프링 중복 빈 해결 방법, Bean이 2개 이상일 때 (0) | 2023.04.01 |