Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: 20231130_CORS_김민협 #56

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions _posts/2023-11-30-cors.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@ banner:

---

# CORS란?
## CORS란?

**CORS**란 “**Cross-Origin Resource Sharing**”의 약자로, **웹 애플리케이션에서 다른 도메인 간에 데이터를 공유할 수 있도록 하는 보안 기술**을 뜻합니다.

한번에 와닿지 않는 개념이기 때문에, 이어지는 개념들을 접하고 나서 다시 이해해보도록 합시다!

## SOP란?
### SOP란?

CORS의 반대되는 개념으로 **SOP**가 있습니다. “**Same-Origin Policy**”의 약자로, **웹 브라우저가 동일 출처에서 로드된 문서 간에만 상호 작용을 허용하는 보안 정책**을 말합니다.

그럼에도 아직 이해가 한번에 되지는 않으리라고 생각합니다.

CORS와 SOP 모두 공통적으로 포함하는 O(Origin)이란 무엇일까요?

### Origin
#### Origin

**Origin**은 **프로토콜, 호스트, 포트로 구성된 URL의 조합**을 말합니다. 아래의 간단한 예시로 확인해 봅시다.

Expand All @@ -53,7 +53,7 @@ CORS와 SOP 모두 공통적으로 포함하는 O(Origin)이란 무엇일까요?
Origin은 “프로토콜, 호스트, 포트”의 조합으로 구성되기 때문에,
이 뒤에 붙는 **Path와 Query String이 다르더라도 Origin의 판별에는 영향을 미치지 않습니다.**

## CORS
### CORS

이제 다시 SOP와 CORS로 돌아와보면, 둘 다 브라우저 보안의 한 종류로 크롬과 같은 **뭽 브라우저에서 설정한 보안 정책**입니다.

Expand All @@ -63,13 +63,13 @@ Origin은 “프로토콜, 호스트, 포트”의 조합으로 구성되기 때

추가로, 이런 CORS error는 **프론트의 요청 방식에 따라** 발생할 수도 있고 발생하지 않을 수도 있습니다.

html의 태그 중에 <img>, <video>, <script>, <link> 등 태그들이 있는데, 이러한 태그들은 기본적으로 Cross-Origin 정책을 지원합니다. 그렇기 때문에 코드의 href나 src에 설정된 다른 사이트, 즉 다른 Origin의 리소스에 접근하는 것이 가능한 것입니다.
html의 태그 중에 img, video, script, link 등 태그들이 있는데, 이러한 태그들은 기본적으로 Cross-Origin 정책을 지원합니다. 그렇기 때문에 코드의 href나 src에 설정된 다른 사이트, 즉 다른 Origin의 리소스에 접근하는 것이 가능한 것입니다.

그러나 XMLHttpRequest, Fetch API 스크립트와 같은 프론트 요청에서는 기본적으로 Same-Origin 정책을 따릅니다.

그렇기 때문에 동일한 기능이라고 하더라도, 태그의 src 요청으로 가져오느냐, 자바스크립트 ajax 요청으로 가져오느냐에 따라 CORS 이슈가 발생하는 것입니다.

## CORS의 필요성
### CORS의 필요성

그렇다면 이러한 CORS는 무슨 필요성이 있길래 이런 혼돈을 우리에게 주는 걸까요?

Expand All @@ -80,7 +80,7 @@ html의 태그 중에 <img>, <video>, <script>, <link> 등 태그들이 있는

사실 출처가 다른 두 어플리케이션이 자유롭게 소통하는 환경은 꽤 위험한 환경이라고 합니다. 만약 CORS와 같은 제약이 없다면 악의적인 유저가 **CSRF**나 **XSS** 등의 방법을 이용해서 개인정보를 가로챌 수 있다고 합니다. 그래서 **필요한 경우에만 다른 Origin 간의 소통(자원 공유)을 허용**해주어야 하는 것입니다.

## CORS의 동작 원리
### CORS의 동작 원리

위에서 다룬 필요성에 따라 서버에서 설정해준 대로, **브라우저가 Origin을 비교하고 차단 여부에 대한 판단을 하는 메커니즘이 CORS**입니다.

Expand All @@ -100,7 +100,7 @@ html의 태그 중에 <img>, <video>, <script>, <link> 등 태그들이 있는

다시 돌아와서 이러한 OPTIONS 메서드에서 응답으로 **적절한 Access-Control-header를 받으면** 실제 요청한 API 콜을 수행할 수 있는 것이고 **그렇지 않으면** CORS error를 반환하는 것입니다.

### CORS와 관련된 response header
#### CORS와 관련된 response header

위의 OPTIONS 메서드의 응답으로 받는, **Access-Control header**에서 **CORS와 관련된 응답 헤더**로는 다음과 같은 것들이 있습니다.

Expand All @@ -118,15 +118,15 @@ html의 태그 중에 <img>, <video>, <script>, <link> 등 태그들이 있는

---

# Spring에서의 CORS Error 해결
## Spring에서의 CORS Error 해결

이제 최종적으로 이러한 **CORS 이슈**에 직면했을 때 **백엔드(Spring)측에서 해결하는 방법**에 대해 알아보겠습니다.

앞에서 살펴본 CORS의 동작 원리에 따르면, **Access-Control-header에 적절한 설정**을 해주면 되는 것이 기본 원리입니다.

이 포스팅에서는 Spring에서 CORS 설정을 해줄 수 있는 3가지 방식에 대해 다루고자 합니다.

## 1. @CrossOrigin 어노테이션
### 1. @CrossOrigin 어노테이션

먼저, 가장 간단한 방법으로 @CrossOrigin 어노테이션이 있습니다. 이 **@CrossOrigin 어노테이션**은 메소드별로 각각 달아줄 수도 있고, 클래스 단위로도 달아줄 수 있습니다.

Expand All @@ -136,7 +136,7 @@ html의 태그 중에 <img>, <video>, <script>, <link> 등 태그들이 있는

위에서 봤던 CORS와 관련된 응답 헤더(Access-Control header)로 조회하는, 백엔드측 CORS 세팅을 해줄 수 있는 것입니다.

## 2. @Configuration으로 전역적인 CORS 설정 (+ Spring Security)
### 2. @Configuration으로 전역적인 CORS 설정 (+ Spring Security)

다음으로, 클래스 레벨을 넘어서 **전역적으로 CORS를 설정**해주고 싶으면 **WebMvcConfigurer를 상속받아 @Configuration으로 구현**하는 방식이 있습니다.

Expand Down Expand Up @@ -187,7 +187,7 @@ public class SecurityConfig {

WebConfig를 따로 두지 않고, **SecurityFilterChain**을 구성할 때 **HttpSecurity의 cors()**를 이용하여 CORS 설정을 해줬습니다. 아래코드의 filterChain()에는 프로젝트의 csrf, JwtTokenFilter 추가 등 다른 Security를 위한 코드들(생략)이 추가되기에, 따로 **corsConfigurationSource()**으로 구현했습니다.

## 3. CorsFilter 커스텀을 통한 전역적인 CORS 설정
### 3. CorsFilter 커스텀을 통한 전역적인 CORS 설정

CorsFilter를 상속하지 않고 Filter를 상속하여 doFilter() 메서드를 오버라이딩하는 방식도 있습니다만, **Spring의 CORS 관련 기능을 더 잘 활용하도록 구현해놓은 CorsFilter를 상속**받는 방식을 소개하도록 하겠습니다.

Expand Down
Loading