백엔드 + 프론트 연결 중
CORS 에러 발생, 근데 preflight는 뭐야?
와이어샤크로 검출해보니
tcp에서 syn -> (syn,ack) - > ack로 3way handshake로 잘 받고
options요청(preflight)으로 보내기 시작하는데 하던 중 갑자기 403을 내려버려서 http요청을 받지도 못하고 종료되었다.
도대체 뭘까?
CORS 에러 트래킹 과정
- postman으로 API요청 확인 → 살아있다면 → 서버 양호
- 개발자도구(F12) 켜서 클라(리액트)로 접근하기 → CORS 확인
SOP(same-origin policy)란?
출처가 다른 애플리케이션이 통신하는 데에 아무런 제약이 없다면
1. 악의적인 사용자가 `CSRF`or`XSS` 등의 공격을 통해 사용자 민감한 정보를 탈취가능
2. 누구나 손쉽게 개발자 도구를 열어 DOM 보기가능
3. 네트워크 탭을 통해 어떤 서버와 통신하는지 확인가능
이러한 이유로, 브라우저는 *출처가 동일한 경우에만 리소스를 공유하도록 한다.
*출처(origin)란?
URL의 구성 요소를 먼저 알아야 한다.
1. scheme(프로토콜)
2. domain name(host)
3. port ~~~~~~등등 으로 이루어진다.
여기서 scheme, host, port 세 가지 합쳐진 것은 origin(출처)
CORS(Cross Origin Resource Sharing)란?
도메인↔도메인의 리소스에 접근할 수 있게 해주는 보안 메커니즘
방금 살펴본 SOP 정책 때문에 다른 출처의 자원은 사용할 수 없음.
웹 환경은 개방되어 있다는 특성, 출처가 서로 다른 곳에서 리소스를 가져와서 사용하는 행위는 상당히 빈번하기에
보안상의 이유로 이러한 것들을 모두 막으면 웹 애플리케이션 원활한 동작이 힘들어짐.
출처가 다른 리소스를 사용할 수 있도록 하는 몇 가지 예외 조항이 있는데, 그중 하나가 CORS정책을 지킨 리소스 요청
⇒ cors정책을 지킨다면 SOP에서 제한하고 있는 행위들의 적용을 받지 않는다.
💡 이때 SOP, CORS 전부 브라우저의 정책이다.
다른 출처의 리소스를 사용하는 것을 제한하는 것은 서버가 아니라 브라우저임❗❗
cors정책은 헤더로 제어합니다.
1. origin
2. Access-Control ~~~
CORS의 상세 동작 흐름
세 가지 시나리오가 존재합니다.
요청을 보내는 쪽: 헤더에 리소스를 필요로 하는 URL을 Origin 필드에 담아서 보낸다
서버: Access-Contrl-Allow-Origin에 리소스 접근이 허용된 출처를 필드에 담아서 보낸다.
간단한 요청인경우 (Simple Request)
- 별다른 절차 없이 다른 출처에 HTTP 요청을 보낼 수 있습니다.(perflight 없음)
- 해당 요청이 CORS를 만족하는지를 체크
복잡한 요청인경우 (Complex Request)
- 간단한 요청 이외의 요청은 전부 복잡한 요청입니다.
- 이 경우부터 요청을 보내기 전에 preflight 요청을 진행합니다.
Credential을 포함한 요청일 경우
- 다른 출처에 요청하는 경우엔 쿠키 정보나 인증과 관련된 헤더를 요청에 포함하지 않습니다.
- 만약 요청에 포함하고자 한다면 credentials 옵션을 사용하면 되는데, 이 옵션에는 3개의 값이 존재합니다
- 마지막은 credential, 즉 HTTP 쿠키와 같이 인증 정보를 포함하는 요청을 보내는 경우입니다.
- 이때, 다른 출처에 인증 정보를 포함하여 요청을 보내는 경우, 서버 측에선 반드시 Access-Control-Allow-Credentials 응답 헤더 값을 true로 설정해야 하고, Access-Control-Allow-Origin 헤더 값에 * (모든 출처를 허용) 대신 반드시 하나의 출처를 명시해야 합니다.
그렇다면 preflight가 필요한 이유가 뭘까?
preflight가 없다면 시나리오는 다음과 같다.
서버는 클라이언트와 만나기 전에 CORS에러가 있는지 모르기 때문이다.
- CORS정책을 맞추었다면: 정상실행이기 때문에 진행한다.
- CORS정책을 맞추지 않았다면: 알맞은 요청이 아님에도 delete, post요청을 먼저 실행하고 그 후에 cors에러인지 알아버린다.
시나리오를 통해서 다시 바라보자.
- 클라에서 브라우저를 통해서 요청
- 브라우저가 서버로 요청전송
- 서버는 CORS인지 모르고 DELETE 진행
- 나 잘했지? 하고 브라우저로 RESPONSE
- 브라우저를 통해서 클라로 보내보니 CORS에러, 그제야 클라에서는 CORS에러 띄운다.
💡 Q: 바보임? 브라우저→서버에서 출처를 아니까 먼저 브라우저가 확인하면 CORS진단되는거 아니야?
A: 웹 환경에서 SOP를 해결하기 위해 CORS로 해결하는데 이것은 origin(출처)가 달라도 리소스를 접근하게 하는 보안 메커니즘이다.
따라서 서버에서 헤더에 `Access-Control-Allow-Origin` , `Access-Control-Max-Age`,
`Access-Control-Allow-Methods` 등을 넣어서 브라우저에게 확인함으로써 그때 CORS를 지켰는지 알 수 있다.
이렇게 되면 올바른 요청이 아님에도 서버는 이미 로직이 실행된 상태
출처
https://jaehyeon48.github.io/web/sop-and-cors/
동일 출처 정책(SOP)과 CORS
이 포스트에선 브라우저의 보안 정책인 동일 출처 정책(Same-Origin Policy)과, CORS(Cross-Origin Resource Sharing)에 대해 알아보겠습니다. Origin 이란? 그 전에 먼저 출처(origin)란 무엇인가에 대해 살펴보겠습
jaehyeon48.github.io
https://gengminy.tistory.com/34
[Spring] 스프링 시큐리티로 CORS와 preflight 설정하기
스프링 시큐리티로 CORS 설정 삽질해서 해결한 과정을 올려본다 사실 결론부터 말하자면 설정은 몇 줄 빼고 아주 잘 되어있었고 도커 이미지 태그가 달라져서 갱신이 안됐던거였다 ^^^^^;;; 로컬
gengminy.tistory.com
'Solo Project > 소셜로그인+JWT' 카테고리의 다른 글
[최종] Spring OAuth2.0 client + 카카오 (로그인, 로그아웃) + JWT (0) | 2024.08.31 |
---|---|
[카카오 소셜 로그인] 1. 순서도 (4) | 2024.07.23 |