티스토리 뷰

 

실제로 사용자가 웹 애플리케이션을 사용할 수 있는 프로젝트를 진행하고 있다. 그렇다면 당연히 보안 이슈가 발생할 것이라 누구나 예상할 수 있다. 백엔드에서 작성한 API를 프론트와 연동하는 과정에서 CORS라는 단어가 계속 나왔다. CORS라는 단어를 처음 들어보는 내 입장에선 당연히 이해할리가 없었다. 심지어 학부 수업에서도 들어본 적이 없다...😅

 

그동안 스프링을 공부하면서 왜 CORS라는 것을 들어보지 못 했을까? 이유는 간단했다. 로컬 환경에서 작업할 때는 CORS를 고려할 필요가 없었기 때문이다. CORS 주로 브라우저에서 실행되는 웹 애플리케이션 간에 적용하는 것이다. 내가 만든 API를 Postman으로 호출해보면서 진행했기 때문에 보안 정책이 필요가 없었다.

 

학교 시험이 끝나면 공부해보고 싶었던 것 중 하나가 CORS 정책이였다. 이번 기회에 확실하게 정리해보겠다.

 

1. SOP(Same-Origin Policy)

동일 출처 정책을 의미하는 SOP는 브라우저의 보안 매커니즘 중 하나이다. 웹 페이지의 스크립트가 다른 출처(domain, protocol, port)의 resource에 접근하는 것을 제한한다. 즉 동일한 출처에 대해서만 서버로 요청을 주고 받을 수 있도록 하는 정책이다.

 

동일한 출처가 무엇인지 예제로 알아보겠다.

  • http://example-site.com:80/example
    • protocol : http
    • domain : example-site.com
    • port : 80
예시 url protocol port 이유
동일한 출처 http://example-site.com:80/example2 http 80 protocol, domain, port 동일
다른 출처 http://example-site.com:8080/example http 8080 port가 다름
다른 출처 https://example-site.com:80/example https 80 protocol이 다름
다른 출처 http://example.com:80/example http 80 domain이 다름  

 

2. CORS(Cross-origin Resource Sharing)

CORS란 교차 출처 리소스 공유라고 한다. 이름에서도 알 수 있듯이 동일한 출처가 아니더라도 서버로 요청을 할 수 있다.

CORS는 웹 브라우저의 보안 정책 중 하나로, 주로 브라우저에서 실행되는 웹 애플리케이션 간에 적용된다. (저번에 이것도 모르고 Postman으로 CORS 테스트를 하고 있었다;;)

 

예시를 들자면, 프론트엔드에서 API를 호출할 때 오류가 발생한다. 이를테면, 프론트엔드에서 브라우저를 통해 백엔드 API로 직접 요청을 보낼 때, 브라우저는 CORS 정책을 적용하여 다른 출처의 리소스에 접근하는 것을 제한할 수 있다. 

 

출처가 다르다면 브라우저 차원에서 보안 문제로 인하여 클라이언트의 요청을 제한하게 된다. 

 

 

3. Preflight Request

Preflight 요청은 GET, POST 등을 사용하여 실제로 요청을 보내기 전에 서버에 미리 확인 요청을 보내는 과정을 의미한다. 

 

브라우저는 실제 요청을 보내기 전에 OPTIONS 메서드를 사용하여 Preflight 요청을 보낸다. 이때, Preflight 요청은 실제 요청과 동일한 URL로 보낸다. 

ex. POST "https://example.com/data" -> OPTIONS "https://example.com/data"

chromium

크로미움의 코드를 보아 HTTP 메서드만 OPTIONS로 변경될 뿐 요청 URL은 동일함을 알 수 있다. 

 

3-1. Preflight 요청 과정

1. Preflight 요청에는 다음과 같은 헤더가 포함된다.

  • Origin : 요청을 보낸 출처(클라이언트의 도메인)
  • Host : 요청을 보내는 서버의 호스트
  • Access-Control-Request-Method : 실제 요청에 사용되는 HTTP 메서드
  • Access-Control-Request-Headers : 실제 요청에 사용되는 헤더
OPTIONS /api/data HTTP/1.1
Host: example.com
Origin: http://example-client.com
Access-Control-Request-Method: POST
Access-Control-Allow-Headers: Content-Type

 

2. 서버는 Preflight 요청을 받으면 클라이언트가 실제 요청을 보내기 전에 해당 요청을 허용할지 결정을 한다.

서버는 Preflight 요청에 대한 응답으로 다음 헤더를 포함하여 클라이언트에게 응답한다.

  • 204 No Content : 서버가 Preflight 요청을 성공적으로 처리했음을 의미한다.
    • Prefligt 요청 특성상 본문에 포함할 데이터가 없다.
  • Access-Control-Allow-Origin : 서버가 허용하는 출처
  • Access-Control-Allow-Methods : 서버가 허용하는 HTTP 메서드
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://example-client.com
Access-Control-Allow-Methods: POST, GET, OPTIONS

 

3. 클라이언트는 실제 요청을 보낸다.

Preflight 요청을 통해 얻은 응답으로부터 클라이언트의 출처가 허용되면 서버로 실제 요청을 보낸다.

POST /api/data HTTP/1.1
Host: example.com
Origin: http://example-client.com
X-Custom-Header: value
Content-Type: application/json

{ "key": "value" }

 

4. 실제 요청에 대하여 서버는 응답을 내린다.

HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: http://example-client.com

{
    "response": "example response"
}
Total
Today
Yesterday
최근에 올라온 글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30