์น ๊ฐ๋ฐ์ ์ฒ์ ์์ํ๋ค๋ณด๋ฉด CORS ์๋ฌ๋ฅผ ๋ฐ๋์ ๋ง๋๊ฒ ๋ฉ๋๋ค.
CORS ์ฒ์ ์ ํ๋ ๊ฒฝ์ฐ ๊ต์ฅํ ๋ง์ ๊ณ ์์ ํ๊ฒ ๋๋๋ฐ์ (์ ๋ ๊ทธ๋ฌ๊ณ ..๐ญ),
์ด๋ฒ ๊ธ์ ํตํด CORS์ ๋ํด ์์ ํ ์ ๋ฆฌํ๊ณ ๋์ด๊ฐ ์ ์์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
CORS(Cross Origin Resource Sharing)์ ๋ํด ์์๋ณด๊ธฐ ์ํด ์ฐ์ O์ ํด๋นํ๋ Origin์ด ๋ฌด์์ธ์ง๋ถํฐ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๐ง Origin
URL์์ ํ๋กํ ์ฝ(Protocol), ํธ์คํธ(Host), ํฌํธ(Port)๋ฅผ ํฉ์น ๊ฒ์ด Origin์ ๋๋ค.
๐ง ๋ค๋ฅธ Origin์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ๋์ ๋ณด์ ๋ฌธ์
(์์๋ฅผ ์ํ ๊ฐ์ ์ ๋๋ค.)
์ ๋ ํ์ฌ ๊นํ๋ธ์ ๊ฐ์ ํ์ฌ ์ฌ์ฉํ๊ณ ์๋๋ฐ์, ๋ก๊ทธ์ธ ์ ๊นํ๋ธ๋ก๋ถํฐ ์ธ์ฆ๊ณผ ๊ด๋ จ๋ ์ฟ ํค๋ฅผ ๋ฐ์์ค๊ฒ ๋ฉ๋๋ค.
์ด๋ ํด์ปค๊ฐ ์ ๋ฉ์ผ๋ก ์ด๋ ํ ๋งํฌ๋ฅผ ํ๋ ๋ณด๋๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
ํด๋น ๋งํฌ๋ ํด๋ฆญํ์ง ์๊ณ ์๋ ๋์ ํ ์ฐธ์ ์ ์์ ์ ๋๋ก ํฅ๋ฏธ๋ก์ด ๋งํฌ์ ๋๋ค.
์ ๋ ํด๋น ๋งํฌ๋ฅผ ๋๋ฅผ ๊ฒ์ด๊ณ , ํด์ปค๊ฐ ๋ง๋ ์ฃผ์๋ก ์ด๋์ ํ๊ฒ ๋ฉ๋๋ค.
์ด๋ ํด๋น ์ฃผ์์ html ํน์ js ํ์ผ์, ๊นํ๋ธ์ ๋ชจ๋ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ญ์ ํ๋ ์ฝ๋๊ฐ ๋ค์ด์์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
๊ทธ๋ ๊ฒ ๋๋ฉด ๋งํฌ ํด๋ฆญ -> ํด์ปค์ ์ฌ์ดํธ ์ ์ -> ์ฝ๋ ์คํ -> ๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ ์ญ์ ์ ์ํฉ์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฌํ ๋ฌธ์ (CSRF ๋๋ XSS ๊ณต๊ฒฉ ๋ฌธ์ )๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด SOP(Same Origin Policy)๊ฐ ๋ฑ์ฅํ์์ต๋๋ค.
๐ง SOP(Same Origin Policy)
Same Origin Policy๋ ์ด๋ฆ ๊ทธ๋๋ก ๊ฐ์ Origin์ ์์ฒญ์ ๋ํด์๋ง ํ๊ฐํ๋ ์ ์ฑ ์ ๋๋ค.
์ด๋ฅผ ํตํด ์์์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋๋ฐ์,
๊นํ๋ธ ์ ์ฅ์์๋ http://hac.ker ์ ์์ฒญ์ด https://github.com๊ณผ ๋ค๋ฅธ Origin์ด๊ธฐ ๋๋ฌธ์ ํด๋น ์์ฒญ์ ๊ฑฐ๋ถํฉ๋๋ค.
์์ ์์ผ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๋ฅผ ๋ณ๋๋ก ๊ตฌ์ฑํ์ง ์์์ผ๋ฏ๋ก ๋ค๋ฅธ Origin์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ํ์๊ฐ ์์์ง๋ง, ์๋๊ฐ ์ง๋จ์ ๋ฐ๋ผ ์น ํ๊ฒฝ์์๋ ๋ค๋ฅธ Origin์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๊ณ ์ฌ์ฉํ๋ ์ผ์ด ๊ต์ฅํ ํํ๊ฒ ๋ฐ์ํ์์ต๋๋ค.
๊ทธ๋ ๋ค ๋ณด๋ ๋ฌด์์ ๋ค๋ฅธ Origin์ ์์ฒญ์ ๋ง๋ ๋์ ๋ช ๊ฐ์ง ์์ธ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ๋์ด ๋ค๋ฅธ Origin๊ฐ์ ๋ฆฌ์์ค ์์ฒญ์ ํ์ฉํ๋๋ก ํ์๋๋ฐ์, ์ด ์ค ํ๋๊ฐ CORS ์ ๋๋ค.
๐ง CORS (Cross Origin Resource Sharing)
CORS๋ ์ถ๊ฐ์ ์ธ HTTP ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ถ์ฒ(Cross Origin)๊ฐ์ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํ ์ ์๋๋ก ํด์ฃผ๋ ์ฒด์ ์ ๋๋ค.
๊ต์ฐจ ์ถ์ฒ๊ฐ ๋ฆฌ์์ค ๊ณต์ ๋ ๊ธฐ๋ณธ์ ์ธ ๊ฒฝ์ฐ์๋ SOP์ ์ํด ๋ฐฉ์ง๋์ด ์์ผ๋, ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ CORS ์์ฒญ์ ํ์ฉํฉ๋๋ค.
- XMLHttpRequest์ Fetch API ํธ์ถ ์
- ์น ํฐํธ(@font-face)์์ ๊ต์ฐจ ๋๋ฉ์ธ ํฐํธ ์ฌ์ฉ ์
- ...
์ด๋ ์์์ผ ํ ์ ์ด, ์ถ์ฒ๋ฅผ ๋น๊ตํ๋ ๋ก์ง์ ์๋ฒ์ ๊ตฌํ๋ ๊ฒ์ด ์๋๋ผ ๋ธ๋ผ์ฐ์ ์ ๊ตฌํ๋์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
์ฆ CORS์ ์๋ฐ๋๋ ์์ฒญ์ ํ๋๋ผ๋, ์์ฒญ์ ๋ฐ๋ ์๋ฒ๊ฐ ๊ฐ์ ์ถ์ฒ์์ ๋ณด๋ธ ์์ฒญ๋ง ๋ฐ๋๋ก ๋ก์ง์ ๊ตฌํํ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด ์๋ฒ๋ ์ ์์ ์ผ๋ก ์๋ต์ ํฉ๋๋ค.
์ดํ ๋ธ๋ผ์ฐ์ ์์ ์ด ์๋ต์ ๋ถ์ํ ๋ค CORS ์๋ฐ์ด๋ผ๊ณ ํ๋จ๋๋ฉด ๊ทธ ์๋ต์ ์ฌ์ฉํ์ง ์๊ณ ๋ฒ๋ฆฌ๋ ๊ฒ์ ๋๋ค.
์ฆ CORS๋ ๋ธ๋ผ์ฐ์ ์ ๊ตฌํ ์คํ์ ํฌํจ๋๋ ์ ์ฑ ์ด๊ธฐ ๋๋ฌธ์, ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํ์ง ์๊ณ ์๋ฒ ๊ฐ์ ํต์ ์ ํ๊ฑฐ๋ Postman ๋ฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ํด๋น ์ ์ฑ ์ด ์ ์ฉ๋์ง ์๋ ๊ฒ์ ๋๋ค.
๋ํ CORS ์ ์ฑ ์ ์๋ฐํ๋ ๋ฆฌ์์ค ์์ฒญ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๊ณ ํด๋ ์๋ฒ ์ชฝ ๋ก๊ทธ์๋ ์ ์์ ์ผ๋ก ์๋ต์ ํ๋ค๋ ๋ก๊ทธ๋ง ๋จ๊ธฐ ๋๋ฌธ์ CORS์ ๋์ ๋ฐฉ์์ ๋ชจ๋ฅด๋ฉด ๊ต์ฅํ ํค๋งฌ ์ ์์ต๋๋ค.
CORS์ ๋์ ์๋ฆฌ๋ฅผ ์์ธํ ์ดํด๋ณด๊ธฐ ์ ์ CORS์์ ์ฌ์ฉ๋๋ HTTP ํค๋์ ๊ฐ๋จํ ์ดํด๋ณด๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
๐ CORS ๊ด๋ จ HTTP ํค๋
๐ฑ ์์ฒญ ํค๋
- Origin : ์์ฒญ์ ์ถ์ฒ๋ฅผ ์๋ฏธํฉ๋๋ค.
- Access-Control-Request-Method : ์์ฒญ์ ๋ณด๋ผ ๋ฉ์๋์ ๋๋ค.
- Access-Control-Request-Headers : ์์ฒญ์ ๋ณด๋ผ ๋ ํฌํจ๋ ํค๋๋ค์ ๋๋ค.
๐ฑ ์๋ต ํค๋
- Access-Control-Allow-Origin : ์๋ฒ์์ ๋ฆฌ์์ค ์์ฒญ์ ํ๋ฝํ Origin๋ค์ ๋๋ค.
- Access-Control-Allow-Methods : ์๋ฒ์์ ๋ฆฌ์์ค ์์ฒญ์ ํ๋ฝํ HTTP Method๋ค ์ ๋๋ค.
- Access-Control-Allow-Headers : ์๋ฒ์์ ๋ฆฌ์์ค ์์ฒญ์ ํ๋ฝํ HTTP Header๋ค ์ ๋๋ค.
- Access-Control-Max-Age : Preflight ์๋ต์ ์บ์ํ๋ ์๊ฐ์ ๋๋ค.
- Access-Control-Allow-Credentials : credentials ๋ชจ๋๊ฐ include์ธ ์์ฒญ์ ํ์ฉํ๊ธฐ ์ํด ์ค์ ํฉ๋๋ค.
- Access-Control-Expose-Headers : ๊ธฐ๋ณธ์ ์ผ๋ก๋ CORS ํ์ฉ ๋ชฉ๋ก ์๋ต ํค๋๋ง ๋ ธ์ถ๋์ง๋ง, ํด๋ผ์ด์ธํธ๊ฐ ๋ค๋ฅธ ํค๋์ ์ก์ธ์คํ ์ ์๋๋ก ํ ๋ ์ฌ์ฉํฉ๋๋ค.
์ด๋ค์ ๋ํด์๋ ๋งจ ๋ง์ง๋ง์์ ์์ธํ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ธ๋ผ์ฐ์ ๋ ์๋์ ๊ฐ์ด ์์ฒญ ํค๋์ ์๋ต ํค๋๋ฅผ ๋น๊ตํ๋๋ฐ์,
์์ฒญ | ์๋ต |
Origin | Access-Control-Allow-Origin |
Access-Control-Request-Method | Access-Control-Allow-Methods |
Access-Control-Request-Headers | Access-Control-Allow-Headers |
์ด๋ CORS ์ ์ฑ ์ ์๋ฐํ๋ค๊ณ ํ๋จํ๋ฉด ์ฆ์ ์๋ฒ๋ก๋ถํฐ ๋ฐ์ ์๋ต์ ๋ฒ๋ฆฌ๊ณ ์์ธ๋ฅผ ๋ฐ์์ํค๊ธฐ ๋๋ฌธ์, ์๋ฒ์์๋ ์ ์ ์๋ต์ด, ํด๋ผ์ด์ธํธ์์๋ CORS ์์ธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋๋ค.
์ถ๊ฐ์ ์ผ๋ก credentials ๋ชจ๋๊ฐ include์ธ ์์ฒญ(์ฟ ํค, ์ธ์ฆ ๊ด๋ จ ํค๋๋ค ๋ฑ์ ์ฌ์ฉ์ ์๋ณ ์ ๋ณด๊ฐ ๋ด๊ธด ์์ฒญ)์ ๋ํด์๋ ๋ณด๋ค ์๊ฒฉํฉ๋๋ค.
์ฐ์ ์์ฒญ์ ๋ณด๋ด๋ ์ธก์์๋ credentials ํญ๋ชฉ์ true๋ก ์ธํ ํด์ผ ํ๊ณ ,
๋ฐ๋ ์ชฝ์์๋ Access-Control-Allow-Origin๋ฅผ ์๋ฌด ์ถ์ฒ๋ ํ์ฉํ๋ค๋ ์์ผ๋์นด๋("*")๊ฐ ์๋๋ผ ๋ณด๋ด๋ ์ชฝ์ Origin์ ์ ํํ ๋ช ์ํ ๋ค Access-Control-Allow-Credentials ํญ๋ชฉ์ true๋ก ๋ง์ถฐ์ฃผ์ด์ผ ํฉ๋๋ค.
์ด๋ ์๋์ Credentialed Request์์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ง CORS ์ ๊ทผ ์ ์ด ์๋๋ฆฌ์ค
CORS ์ ๊ทผ ์ ์ด ์๋๋ฆฌ์ค์๋ 3๊ฐ์ง ์ํฉ์ด ์์ต๋๋ค.
์ด๋ค์ ๊ฐ๊ฐ Simple Request(๋จ์ ์์ฒญ), Preflight Request(ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ), Credentialed Request(์ธ์ฆ์ ๋ณด๋ฅผ ํฌํจํ ์์ฒญ)์ด๋ฉฐ, ํ๋ํ๋ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๐ง Simple Request
๋ค์์ ์ดํด๋ณผ Preflight์๋ ๋ฌ๋ฆฌ, ๋ณธ ์์ฒญ์ ๋ฐ๋ก ๋ณด๋ด๋ฉด์ ๊ทธ ์ฆ์ Cross Origin์ธ์ง ํ์ธํ๋ ์์ฒญ์ ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์กฐ๊ฑด์ ๋ชจ๋ ์ถฉ์กฑํ๋ ์์ฒญ์ Simple Request๋ฅผ ํตํด ์์ฒญํ๊ฒ ๋ฉ๋๋ค.
๐ ์กฐ๊ฑด 1
HTTP Method๋ ๋ค์ ์ข ๋ฅ ์ค ํ๋์ฌ์ผ ํฉ๋๋ค.
- GET
- POST
- HEAD
๐ ์กฐ๊ฑด 2
Content Type์ ๋ค์ ์ข ๋ฅ ์ค ํ๋์ฌ์ผ ํฉ๋๋ค.
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
๐ ์กฐ๊ฑด 3
HTTP Header๋ ๋ค์ ์ข ๋ฅ๋ง ํ์ฉํฉ๋๋ค.
- Accept
- Accept-Language
- Content-Language
- Content-Type
Simple Request์ 2๋ฒ ์กฐ๊ฑด์ ๋ณด๋ฉด application/json์ด ํ์ฉ๋์ง ์์ผ๋ฉฐ, 3๋ฒ ์กฐ๊ฑด์ ๋ณด๋ฉด ์ธ์ฆ์ ์ฌ์ฉ๋๋ Authorization ํค๋ ์กฐ์ฐจ ํฌํจ๋์ง ์์ต๋๋ค.
์ด๋ก ์ธํด Simple Request๋ ์ผ๋ฐ์ ์ธ ์ํฉ์์๋ ๊ฑฐ์ ๋ฐ์ํ์ง ์๋ ์์ฒญ์ ๋๋ค.
๐ Simple Request ์๋๋ฆฌ์ค
์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ํตํด https://bar.other๋ก ์์ฒญ์ ๋ณด๋ด๋ ์ํฉ์ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';
xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();
์ด ๊ฒฝ์ฐ Simple Request ์กฐ๊ฑด์ ๋ชจ๋ ๋ถํฉํ๊ธฐ ๋๋ฌธ์, Simple Request๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด๋ ๋ธ๋ผ์ฐ์ ์ ์๋ฒ๊ฐ์ ์์ฒญ๊ณผ ์๋ต ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ฑ ์์ฒญ
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101
Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive Origin: https://foo.example
Origin: https://foo.example
์์ฒญ ํค๋์ Origin์ ๋ณด๋ฉด https://foo.example๋ก๋ถํฐ ์์ฒญ์ด ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๐ฑ ์๋ต
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[…XML Data…]
์๋ฒ๋ ํด๋น ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก Access-Control-Allow-Origin ํค๋๋ฅผ ์ ์กํฉ๋๋ค.
์ด๋ ์๋ฒ๋ ์์ผ๋์นด๋(*)๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ Origin์ ๋ํ ์์ฒญ์ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ํด๋น ์์ฒญ์ ์ฑ๊ณตํฉ๋๋ค.
๋ง์ฝ https://bar.example ์๋ฒ์์ ์ค์ง https://foo.example ์ ์์ฒญ๋ง์ ํ์ฉํ๋ ค๊ณ ํ๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํด์ผ ํฉ๋๋ค.
Access-Control-Allow-Origin: https://foo.example
๐ง Preflight Request
Simple Request์๋ ๋ฌ๋ฆฌ ๋ณธ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ ์ OPTIONS ๋ฉ์๋๋ฅผ ํตํด์ ๋ฏธ๋ฆฌ HTTP ์์ฒญ์ ๋ณด๋ด ๋ณธ ์์ฒญ์ ์ ์กํ๊ธฐ์ ์์ ํ์ง ํ์ธํ๋ ์์ฒญ์ ๋๋ค.
(์ฆ ์์ฒญ์ 2๋ฒ ๋ฐ์ํ๋ฉฐ, Preflight ์์ฒญ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์์์ ๋ณด๋ด๋ ๊ฒ์ด๋ฏ๋ก ๋ฐ๋ก Preflight ์์ฒญ์ ์์ฑํ์ฌ ๋ณด๋ผ ํ์๊ฐ ์์ต๋๋ค.)
๐ Preflight Request ์๋๋ฆฌ์ค
์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ํตํด https://bar.other๋ก ์์ฒญ์ ๋ณด๋ด๋ ์ํฉ์ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
const xhr = new XMLHttpRequest();
xhr.open("POST", "https://bar.other/doc");
xhr.setRequestHeader("X-PINGOTHER", "pingpong");
xhr.setRequestHeader("Content-Type", "text/xml");
xhr.onreadystatechange = handler;
xhr.send("<person><name>Arun</name></person>");
ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ์ ์ฒด ํต์ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ฑ Preflight ์์ฒญ
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101
Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
OPTIONS ๋ฉ์๋๋ฅผ ํตํด Preflight Request๋ฅผ ์ ์กํฉ๋๋ค.
Preflight Request๋ฅผ ์ ์กํ ๋์๋ Access-Control-Request-Method์ Access-Control-Request-Headers๋ผ๋ ๋ ๊ฐ์ ์์ฒญ ํค๋๊ฐ ์ถ๊ฐ๋ก ์ ์ก๋ฉ๋๋ค.
๐ฑ Preflight ์๋ต
HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
์ฐ์ Access-Control-Allow-Origin์ https://foo.example์ด ํฌํจ๋์ด ์์ผ๋ฏ๋ก https://foo.example์ ์์ฒญ์ ํ์ฉํฉ๋๋ค.
Access-Control-Allow-Methods ํค๋์๋ POST, GET, OPTIONS ๋ฉ์๋๋ฅผ ํ์ฉํ๋ค๊ณ ๋ช ์๋์ด ์์ต๋๋ค.
Access-Control-Allow-Headers ํค๋๋ X-PINGOTHER, Content-Type ์ด๋ผ๋ ํค๋๋ฅผ ํ์ฉํ๋ค๋ ์๋ฏธ์ ๋๋ค.
์ด๋ฅผ ํตํด ๋ธ๋ผ์ฐ์ ๋ X-PINGOTHER์ Content-Type์ด๋ผ๋ ํค๋๋ฅผ ๋ณธ ์์ฒญ์์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ๋ฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก Access-Controler-Max-Age๋ ๋ค๋ฅธ Preflight Request๋ฅผ ๋ณด๋ด์ง ์๊ณ , preflight request์ ๋ํ ์๋ต์ ์บ์ํ ์ ์๋ ์๊ฐ(์ด)๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํด๋น ์๋ฒ์์๋ 86400์ด๋ก ์ค์ ๋์ด ์์ต๋๋ค.
๐ฑ ์ค์ ์์ฒญ
POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101
Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache <person><name>Arun</name></person>
๐ฑ ์๋ต
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain
[Some GZIP'd payload]
๐ ์ฐธ๊ณ : Vary
์๋ฒ๊ฐ Access-Control-Allow-Origin: * ๋์ ์ ํน์ ํ origin์ ์ง์ ํ ๊ฒฝ์ฐ,
์๋ฒ๋ Vary ์๋ต ํค๋์ Origin์ ํฌํจํด์ผ ํฉ๋๋ค.
๐ Preflight๋ฅผ ์ฌ์ฉํ๋ ์ด์
CORS์ ๋งค์ปค๋์ฆ์ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ์ด ์์ต๋๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ธ๋ค.
- ์๋ฒ๋ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ๋ค.
- ์๋ฒ์์ ์์ฒญ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์๋ตํ๋ค.
- ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )์์ ์๋ต์ ๋ฐ๊ณ , CORS ์ ์ฑ ์๋ฐ์ธ์ง ํ์ธํ๋ค.
- ์ ์ฑ ์๋ฐ์ด๋ผ๋ฉด ํด๋น ์๋ต์ ๋ฒ๋ฆฐ๋ค. (์? ์ด๋ฏธ ์๋ฒ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋๋ฐ..?)
๋ง์ฝ CORS ์ ์ฑ ์ ์๋ฐํ๋ ์์ฒญ์ด ์๋ฒ์ DB๋ฅผ ๋ชจ๋ ์ง์ด๋ค๋๊ฐ, ์ฌ์ฉ์๋ฅผ ํํด์ํค๋ ๋ฑ ์๋ฒ์ ๋ฆฌ์์ค์ ์ํฅ์ ์ฃผ๋ ์์ฒญ์ด๋ผ๋ฉด ์๋ฒ๋ ์ด๋ฏธ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ๋ณ๊ฒฝํ ๊ฐ๋ฅ์ฑ์ด ์๋ ์์ฒญ(Simple Request์ ์กฐ๊ฑด์ ๋ถํฉํ์ง ์๋ ์์ฒญ)์ ๋ํด์๋ ํด๋น ์์ฒญ์ด ์๋ฒ์ ๋ณด๋ด๋ ์์ ํ์ง๋ฅผ ๋จผ์ ํ์ธํด์ผ ํ๋ ์์ ์ด ํ์ํ๋ฉฐ, ์ด๋ฅผ ์ํด Preflight๊ฐ ๋ฑ์ฅํ๊ฒ ๋์์ต๋๋ค.
(Simple Request๋ ์์ฒญ์ด ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ธฐ ๋๋ฌธ์ Preflight ์์ฒญ์ด ๋ฐ์ํ์ง ์๋๋ค๊ณ ํ์์ง๋ง, ์ด๋ ์๋ฒ์ ๊ตฌํ์ ๋ฐ๋ผ ์ถฉ๋ถํ ์๋ฒ์ ๋ฆฌ์์ค๊ฐ ๋ณ๊ฒฝ๋๊ฒ ๋ง๋ค ์ ์์ผ๋ฏ๋ก ์๋ฒ ๊ฐ๋ฐ์๋ ์ด๋ฅผ ํญ์ ์ผ๋ํด ๋๊ณ ๊ฐ๋ฐ์ ํด์ผ ํฉ๋๋ค.)
Preflight Request ๋ฐฉ์์ ์์ฒญ์ด ์ด 2๋ฒ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
๊ทธ๋์ Preflight ์์ฒญ์ ์๋ต์ ์บ์ฑํ์ฌ ํน์ ๊ธฐ๊ฐ ๋์์ ๋ค์ Preflight ์์ฒญ์ ๋ฐ์์ํค์ง ์๋๋ก ํ ์ ์๋๋ฐ์,
Access-Control-Max-Age์ Preflight ์์ฒญ์ ์บ์ฑ ๊ธฐ๊ฐ์ ์ง์ ํด์ค ์ ์์ต๋๋ค.
๐ง Credentialed Request
credentials ํ๋๊ทธ๊ฐ true์ธ ์์ฒญ์ ๊ฒฝ์ฐ Credentialed Request๋ฅผ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๊ต์ฐจ ์ฌ์ดํธ(Cross-Site)๊ฐ XMLHttpRequest ํน์ Fetch ์์ฒญ์์ ๋ธ๋ผ์ฐ์ ๋ ์ธ์ฆ ๊ด๋ จ ์ ๋ณด๋ฅผ ๋ณด๋ด์ง ์์ต๋๋ค.
credentialed ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํด์๋ ์ด๋ฅผ ์ค์ ํด ์ฃผ์ด์ผ ํ๋๋ฐ์,
Fetch api์ ๊ฒฝ์ฐ credentials ์ต์ ์ ์ค์ ํ์ฌ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ณด๋ผ ์ ์์ผ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ์ข ๋ฅ๊ฐ ์์ต๋๋ค.
์ต์ | ์ค๋ช |
same-origin (default) | ๊ฐ์ ์ถ์ฒ๋ก์ ์์ฒญ์๋ง ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ |
include | ๋ชจ๋ ์์ฒญ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ |
omit | ๋ชจ๋ ์์ฒญ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ง ์์ |
fetch('http://bar.other/resources/credentialed-content/', {
credentials: 'include', // Credentials ์ต์
๋ณ๊ฒฝ!
});
XMLHttpRequest๋ ์๋์ ๊ฐ์ด ํน์ ํ๋ ๊ทธ๋ฅผ ์ค์ ํ์ฌ์ผ ํฉ๋๋ค.
const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';
function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true; // ์ธ์ฆ ์ ๋ณด ๋ณด๋ด๊ธฐ ์ํจ
invocation.onreadystatechange = handler;
invocation.send();
}
}
๐ Credentialed Request ์๋๋ฆฌ์ค
์ XMLHttpRequest๋ฅผ ์์๋ก ๊ณ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ ์ Simple Request ์กฐ๊ฑด์ ๋ถํฉํ๋ฏ๋ก Preflight ๋์ง ์์ต๋๋ค.
์ดํ ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )๋ ์๋ฒ์ ์๋ต ํค๋์ Access-Control-Allow-Credentials: true๊ฐ ์๋ค๋ฉด ํด๋น ์๋ต์ ๊ฑฐ๋ถํฉ๋๋ค.
์ด๋ค๊ฐ์ ์์ฒญ๊ณผ ์๋ต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ฑ ์์ฒญ
GET /resources/credentialed-content/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101
Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2
์ฟ ํค๊ฐ ํฌํจ๋๊ธฐ ๋๋ฌธ์ credentialed request ์ ๋๋ค.
๐ฑ ์๋ต
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
[text/plain payload]
๋ง์ฝ Access-Control-Allow-Credentials: true๊ฐ ์๋ค๋ฉด ์๋ต์ ๋ฌด์๋ฉ๋๋ค.
๐ Credentialed Request์ ์์ผ๋์นดํธ
Credentialed Request์ ์๋ตํ ๋ ์๋ฒ๋ ๋ฐ๋์ ์์ผ๋์นด๋(*)๋ฅผ ์ง์ ํ๋ ๋์
Access-Control-Allow-Origin ํค๋ ๊ฐ์ ์ถ์ฒ๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ ์๋๋ฆฌ์ค์ ์์ฒญ ํค๋์๋ Cookie๊ฐ ํฌํจ๋์ด ์์ผ๋ฏ๋ก Credentialed Request์ด๋ฉฐ,
์๋ฒ์์ Access-Control-Allow-Origin: * ์ผ๋ก ์ค์ ํ๋ค๋ฉด ์คํจํ๊ฒ ๋ฉ๋๋ค.
(Access-Control-Allow-Origin: * ์ ํ ์ํ์์ Access-Control-Allow-Credentials: true๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.)
๐ง ํค๋ ์ดํด๋ณด๊ธฐ
(์์์ ๋์ค์ง ์์๊ฑฐ๋ ์ถ๊ฐ ์ค๋ช ์ด ํ์ํ ํค๋๋ง ์ดํด๋ณด๊ฒ ์ต๋๋ค)
๐ Access-Control-Expose-Headers
๋ธ๋ผ์ฐ์ ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก CORS ํ์ฉ ๋ชฉ๋ก ์๋ต ํค๋๋ง ๋ ธ์ถ๋์ง๋ง, ๋ธ๋ผ์ฐ์ ๊ฐ ๋ค๋ฅธ ํค๋์ ์ก์ธ์คํ ์ ์๋๋ก ํ ๋ ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์๋ฒ๊ฐ ์ด๋ค ์์ฒญ์ ์๋ต์ผ๋ก Location ํค๋๋ฅผ ๋ฐํํ๋ค๋ฉด, Access-Control-Expose-Headers: Location์ ํตํด ๋ธ๋ผ์ฐ์ ์์ Location ํค๋์ ์ ๊ทผํ ์ ์๋๋ก ํด์ฃผ์ด์ผ ํฉ๋๋ค.
๐ Access-Control-Allow-Credentials
credentials ํ๋๊ทธ๊ฐ true์ธ ์์ฒญ์ ๋ํ ์๋ต์ ํ์ํ ์ ์๋์ง๋ฅผ ๋ํ๋ ๋๋ค.
Preflight request์ ๋ํ ์๋ต์ ์ผ๋ถ๋ก ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์๋ credentials๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ์์ฒญ์ ์ํํ ์ ์๋์ง๋ฅผ ๋ํ๋ ๋๋ค.
Simple reqeust์ ๊ฒฝ์ฐ preflight๋์ง ์์ผ๋ฏ๋ก credentials ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก Access-Control-Allow-Credentials: true๊ฐ ์๋ค๋ฉด ์๋ต ๊ฒฐ๊ณผ๋ ๋ฌด์๋ฉ๋๋ค.
๐ Reference
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS#requests_with_credentials
๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (CORS) - HTTP | MDN
๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (Cross-Origin Resource Sharing, CORS)๋ ์ถ๊ฐ HTTP ํค๋๋ฅผ ์ฌ์ฉํ์ฌ, ํ ์ถ์ฒ์์ ์คํ ์ค์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ ์ถ์ฒ์ ์ ํํ ์์์ ์ ๊ทผํ ์ ์๋ ๊ถํ์ ๋ถ์ฌํ๋๋ก ๋ธ๋ผ
developer.mozilla.org
https://fetch.spec.whatwg.org/#http-cors-protocol
Fetch Standard
fetch.spec.whatwg.org
'๐ ๋คํธ์ํฌ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[๋คํธ์ํฌ] ์ฟ ํค์ ์ธ์ , ํ ํฐ์ ์ด์ฉํ ์ธ์ฆ (0) | 2023.05.08 |
---|