티스토리 뷰
개요
현업에서도 많이 들었으나 잘 이해가 가지 않았던 CORS 가 뭔지 공부하고
해당 링크의 내용을 정리한다.
https://ko.javascript.info/fetch-crossorigin#ref-400
내용
cors 란?
- 브라우저에서 실행중인 스크립트에서 시작되는 cross-origin Http 요청을 제한하는 브라우저 보안 기능.
- 제한한 cross-origin HTTP 요청을 하기 위해 서버의 동의가 필요함.
- 동의시 브라우저에서는 요청 허용, 동의하지 않는 경우엔 브라우저에서 거절하는 메커니즘은 HTTP-header를 이용하는데 이것이 바로 CORS
Cross-origin이란?
아래 3가지 중 하나라도 다른 경우를 지칭함.
1. 프로토콜
2. 도메인
3. 포트번호
CORS가 왜 필요한가?
과거 수 년 동안, 한 사이트의 스크립트에서 다른 사이트에 있는 콘텐츠에 접근할 수 없다는 제약이 있었으나
그 당시 js는 네트워크 요청을 보낼 수 있을만한 메서드를 지원하지 않음.
.
이로 인해 그 당시 정해져있던 보안 규칙을 피해 다른 웹 사이트에 요청을 보내기 위한 트릭을 만들기 시작함.
1. <form> 태그 사용.
<!-- 폼 target -->
<iframe name="iframe"></iframe>
<!-- 자바스크립트를 사용해 폼을 동적으로 생성하고 보냄-->
<form target="iframe" method="POST" action="http://another.com/…">
...
</form>
네트워크 관련 메서드는 없었으나, 폼은 어디든 데이터를 보낼 수 있다는 특징을 이용함.
다만 다른 사이트에서 <iframe> 에 있는 콘텐츠를 읽는 것이 금지되었기에 응답을 읽는 것은 불가능함.
이를 해결하기 위해 iframe과 페이지 양쪽에 스크립트를 심어 제약을 피해감.
2. 스크립트 사용
스크립트 태그의 src 속성값에 도메인 제약이 없기에 이 특징을 이용하여 어디서든 스크립트를 실행할 수 있음.
<script src= "http://..... "> 형태로 도메인에 데이터 요청을 하게 되면 'jsonp'라 불리는 프로토콜을 사용해 데이터를 가져오게 됨.
이러한 꼼수로 양방향 데이터 전달을 받을 수 있었으나 브라우저측 js에서도 네트워크 관련 메서드가 추가된 뒤 논의 끝에 cross origin Request를 허용하기로 결정함.
다만 cross origin Request를 허가했다는 것을 알려주기 위해 특별한 헤더를 전송받았을 때만 가능하도록 제약을 걸게 됨.
안전한 요청이란?
아래 두 가지 조건을 모두 충족하는 요청
1. 안전한 메서드 (safe method) - GET, POST, HEAD 를 사용한 요청
2. 안전한 헤더 (safe header) - 아래 목록에 속하는 헤더
- Accept
- Accept-Language
- Content-Language
- 값이 application/x-www-form-urlencoded이나 multpart/form-data, text/plain인 Content-Type
근본적인 차이는 특별한 방법을 사용하지 않고도 <form> 이나 <script>를 사용해 요청할 들 수 있다는 점에 있음.
브라우저는 'preflight' 요청을 먼저 전송해 서버가 cross origin Reques를 받을 수 있는 준비가 되어있는지 확인함.
이때 서버에서 cross origin Reques를 허용하지 않는 정보를 담은 헤더를 브라우저에 응답하면 안전하지 않은 요청으로 서버로 전송되지 않는다.
CORS와 안전한 요청 절차
1. cross origin Reques를 보낼 경우 브라우저는 항상 Origin 이라는 헤더를 요청에 추가한다.
2. 서버는 요청 헤더에 있는 Origin을 검사하고, 요청을 받아들이기로 동의했다면 Access-Control-Allow-Origin이라는 응답을 추가한다.
3. Access-Control-Allow-Origin엔 허가한 Origin 정보가 동일하게 들어있거나 *이 들어있다.
이 과정에서 브라우저는 중재인의 역활을 한다.
- cross origin Reques를 보낼 경우 Origin에 값이 제대로 설정, 전송되었는지 확인함.
- 서버로부터 받은 응답에 Access-Control-Allow-Origin가 존재하는지 확인하고, 요청을 동의했는지 확인함.
- 동의시 js를 사용해 응답에 접할 수 있고, 아닌 경우엔 에러가 발생함.
응답 헤더
cross origin Reques가 이루워진 경우 js는 기본적으로 안전한 응답 헤더로 분류되는 헤더에만 접근할 수 있다.
- Cache-Control
- Content-Language
- Content-Type
- Expires
- Last-Modified
- Pragma
이 외 응답 헤더에 접근 시 에러가 발생되고 접근해야 한다면 Access-Control-Expose-Headers라는 헤더를 보내줘야 함.
...
...
API-Key: 2c9de507f2c54aa1
Access-Control-Allow-Origin: https://....
Access-Control-Expose-Headers: API-Key, ..., ...
CORS와 안전하지 않은 요청 절차
과거의 웹페이지는 GET, POST 이외의 HTTP 메서드를 사용해 요청 보낼 수가 없었음.
DELETE, PATCH 등의 메서드가 추가되며 브라우저는 '안전하지 않은' 요청이 이루워지는 경우 서버에 바로 요청을 보내지 않고 'preflight' 요청이라는 사전 요청을 서버에 보내 권한을 확인함.
preflight 요청은 OPTIONS 메서드를 사용하고 두 헤더가 함께 포함되며 본문은 비어있는 형태임.
1. Access-Control-Request-Method - 안전하지 않은 요청에 사용하는 메서드 정보가 담겨져 있음.
2. Access-Control-Request-Header - 안전하하지 않은 요청에 사용하는 헤더 목록이 담겨져 있고 쉼표로 구분됨.
요청을 허가하였다면 본문이 비어있고, 상태 코드가 200인 응답을 아래 헤더와 함께 브라우저로 전송함
1. Access-Control-Allow-Origin - *이나 요청을 보낸 오리진 정보여야함.
2. Access-Control-Allow-Method - 허용된 메서드 정보
3. Access-Control-Allow-Header - 허용된 헤더 목록
4. Access-Control-Max-Age - 퍼미션 체크 여부 및 몇 초간 캐싱해 놓을지 명시함.
- 명시된 일정 기간동안 preflight 요청을 생략하고 안전하지 않은 요청을 보낼 수 있다.
자격 증명(credential)
cross origin Reques를 보낼 경우 기본적으로 쿠키와 HTTP 인증 같은 자격 증명이 함께 전송되지 않음.
fetch('tttp:// ....')을 사용하여 요청보내도 해당 요청 도메인의 관련 쿠키가 전송되지 않는 다는 것.
HTTP 요청은 대부분 쿠키가 전송되는 것에 비해 cross origin Reques 는 예외적이다.
이런 예외가 생긴 이유는 자격 증명과 함께 전송하게 되면 사용자 동의 없이 js로 민감한 정보에 접근할 수 있게 되기 때문.
그럼에도 이를 서버에서 허용하고 싶다면, 자격 증명이 담긴 헤더를 명시적으로 허용하겠다는 세팅을 서버에서 해줘야함.
fetch('http://....', {
credentials: "include"
});
자격 증명 정보가 담긴 요청을 서버에서 받아들이기로 동의했다면 서버는 응답에 아래 헤더를 추가해서 보내야한다.
200 OK
Access-Control-Allow-Origin: https://....
Access-Control-Allow-Credentials: true
'새롭게 시작하는 개발 이야기' 카테고리의 다른 글
javascript와 단일 쓰레드의 관계 - 3월 15일 스터디 발표. (2) | 2023.03.15 |
---|---|
Browser Rendering 과정 - 3월 9일 스터디 발표 (0) | 2023.03.09 |
HTTP와 HTTPS의 차이점 - 스터디 발표 3월 2일 (0) | 2023.03.02 |
h2 관련 명령어 (0) | 2022.08.21 |
SubProject끼리 의존성 주입하기 (0) | 2022.07.29 |
- Total
- Today
- Yesterday
- web
- 인텔리J
- 개발일지
- RequestHandler
- 일지
- @Autowired
- HTTP
- 스터디 회고
- 회고
- 한 입 크기로 잘라먹는 리액트
- 프로그래머스
- mapping
- 개발
- header
- graphQL
- JAR
- springboot
- 자바스크립트
- 멀티모듈
- Java
- Spring
- MySQL
- 모듈
- JavaScript
- homebrew
- body
- Spring Boot
- Gradle
- Request Handler
- spring-boot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |