CORS
Cross-Origin Resource Sharing, CORS ๋ ์๋ก ๋ค๋ฅธ Origin ๊ฐ์ ์์์ ๊ณต์ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
CORS ๋ฅผ ์ดํดํ๊ธฐ ์ํด์ ๋จผ์ Origin ๊ณผ SOP ๋ผ๋ ๊ฐ๋ ์ ์์์ผ ํ๋ค.
Origin
Origin ์ ์ง์ญํ๋ฉด ์ถ์ฒ
๋ก URL ์ Protocol
Host
Port
๋ก ์ ์๋๋ค. ์ฆ, Origin ์ด ๊ฐ๋ค๋ ๊ฒ์ URL ์ Protocol
Host
Port
๊ฐ ๋ชจ๋ ๋์ผํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ฒ์ ๋ธ๋ผ์ฐ์ ๋ฅผ ํค๊ณ https://www.naver.com
์ ์ ์ํ๋ฉด index.html
๋ฉ์ธ ํ์ด์ง๋ฅผ ๋ฐ์ํ
๋ฐ ํด๋น ํ์ด์ง์์ ์ ์กํ๋ ๋ชจ๋ ์์ฒญ์ Origin ์ https://www.naver.com
์ด ๋๋ ๊ฒ์ด๋ค.
์ ์์ฒญ์ ๋ค์ด๋ฒ ๊ธ์ต ํ์ด์ง์์ ํ์ธํ ์ ์๋ ์์ฒญ์ด๋ค. Origin ์ด ๋ค๋ฅธ Origin ์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ๋ Origin
ํค๋๊ฐ ํฌํจ๋์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
SOP
Same-Origin Policy, SOP ๋ ์ง์ญํ๋ฉด ๋์ผ ์ถ์ฒ ์ ์ฑ
์ผ๋ก ๋ค๋ฅธ Origin ์ผ๋ก ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ ๊ธ์งํ๋ ๋ธ๋ผ์ฐ์ ์ ๊ธฐ๋ณธ ๋ณด์ ์ ์ฑ
์ด๋ค. ์ฆ, ๋์ผํ Origin ์ผ๋ก๋ง ์์ฒญ์ ๋ณด๋ผ ์ ์๊ฒ๋ ๊ฐ์ ํ๋ ๊ฒ์ด๋ค.
๊ณผ๊ฑฐ ์น์ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๋ฅผ ๋ณ๋๋ก ๊ตฌ๋ถํ์ง ์๋ ๋์ ์๋ฒ๊ฐ ์ง์ ์์ฒญ์ ์ฒ๋ฆฌํ ๊ฒฐ๊ณผ๋ฅผ HTML ๋ฌธ์๋ก ๋ง๋ค์ด ํด๋ผ์ด์ธํธ์๊ฒ ์ ๊ณตํ๋ค. ์ด๋ ๋ชจ๋ ์ฒ๋ฆฌ๊ฐ ๊ฐ์ Origin ์์ ์ผ์ด๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ฆ, ๊ณผ๊ฑฐ ๋ธ๋ผ์ฐ์ ์์ ๋ค๋ฅธ Origin ์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ํ์๊ฐ ์์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ Origin ์ผ๋ก ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ ์ ์์ ์ธ ํ์๋ก ๊ฐ์ฃผํ์ฌ SOP ๋ผ๋ ์ ์ฑ ์ ํตํด ๋ธ๋ผ์ฐ์ ์์ ๋ง์๋ ๊ฒ์ด๋ค.
์๋๊ฐ ํ๋ฅด๊ณ ์น ๊ธฐ์ ์ด ๋ฐ์ ํจ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ถ์ฒ๋ก ์์ฒญ์ ํ๋ ์์๊ฐ ์ฆ๊ฐํ๋ค. ํ์ง๋ง SOP ๋ผ๋ ๋ธ๋ผ์ฐ์ ์ ์ฑ ๋๋ฌธ์ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ๋ถ๊ฐ๋ฅํ๊ธฐ์ CORS ๋ผ๋ ๊ฐ๋ ์ด ๋ฑ์ฅํ ๊ฒ์ด๋ค.
์ฆ, CORS ๋ ๊ธฐ์กด SOP ์ ์ํด ์ ํ๋์๋, ๋ค๋ฅธ Origin ์ผ๋ก ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํด ์ง์ผ์ผ ํ๋ ์ ์ฑ ์ธ ๊ฒ์ด๋ค.
SOP ์ ํ์์ฑ
๋ธ๋ผ์ฐ์ ๋ ์ SOP ๊ฐ์ ์ ์ฑ ์ ๋ง๋ค์ด์ ํต์ ํ๊ธฐ ์ํด CORS ๊ฐ์ ๋ถ๊ฐ์ ์ธ ์์ ์ ์ํํด์ผ ํ ๊น? SOP ๊ฐ ๋ง์ฝ ์์๋ค๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํ๊ธฐ์ ์ด๋ฐ ์ ์ฑ ์ด ํ์ํ ๊น?
์ ๋ํ ์ฌ์ฉ์๊ฐ ๊ตฌ๊ธ์ ๋ค์ด๋ฒ์ ๋ก๊ทธ์ธ์ด ๋ ์ํ๋ก www.hacker.com
๋ผ๋ ํผ์ฑ ์ฌ์ดํธ์ ์ ๊ทผํ๋ค๊ณ ์๊ฐํด๋ณด์. ํผ์ฑ ์ฌ์ดํธ์ ๋ค์ด๋ฒ์ ๊ฐ์ธ ์ ๋ณด๋ฅผ ์์ฒญํ๋ ์คํฌ๋ฆฝํธ๊ฐ ์์ฑ๋์ด ์๋ค.
ํผ์ฑ ์ฌ์ดํธ์ ์ ์ํ๋ ์๊ฐ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋์ด ๋ณธ์ธ์ ๋ธ๋ผ์ฐ์ ๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ค์ด๋ฒ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฌ์ฉํด ๊ฐ์ธ ์ ๋ณด๊ฐ ๋ ธ์ถ๋๋ ์ผ์ด ๋ฐ์ํ๋ค. ์๋ฒ ์ ์ฅ์์ ์ ์์ ์ธ ์ธ์ฆ์ ๋ณด๋ฅผ ํตํด ์์ฒญ์ ๋ณด๋๊ธฐ ๋๋ฌธ์ ํด๋น ์์ฒญ์ด ์ ์์ ์ธ ์์ฒญ์ด๋ผ๋ ๊ฒ์ ํ๋ณํ ์ ์์ ๊ฒ์ด๋ค. ์ด๊ฒ์ด ๋ฐ๋ก CSRF ๊ณต๊ฒฉ์ด๋ค.
SOP ์ ์ฑ
์ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ๋ค. www.hacker.com
์ด๋ผ๋ Origin ์์ ๋ค์ด๋ฒ์๊ฒ ์์ฒญ์ ๋ณด๋์ผ๋ ๋ธ๋ผ์ฐ์ ์
์ฅ์์ ์๋ก ๋ค๋ฅธ Origin ์์ ์์ฒญ์ ํ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๊ฒ ๋์ด ํด๋น ์์ฒญ ์์ฒด๋ฅผ ๋ง์๋ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
CORS ์ ๊ทผ ์ ์ด ์๋๋ฆฌ์ค
Simple Request
CORS ๋ฅผ ๋ง์กฑํ๊ธฐ ์ํด์ Preflight ์์ฒญ์ ํตํด CORS ํ์ฉ ์ฌ๋ถ๋ฅผ ๋จผ์ ํ์ธํด์ผ ํ๋๋ฐ, ์๋ ์กฐ๊ฑด์ ๋ชจ๋ ์ถฉ์กฑํ๋ ์์ฒญ์ ๊ฒฝ์ฐ Preflight ์์ฒญ์ด ๋ถํ์ํ ์์ ํ ์์ฒญ์ด๋ผ๊ณ ํ๋จํ์ฌ ํ ๋ฒ๋ง ์์ฒญํ๋ Simple Request ๋ฅผ ๋ณด๋ธ๋ค.
GET
POST
HEAD
๋ฉ์๋๋ง ํ์ฉAccept
Accept-Language
Content-Language
Content-Type
ํค๋๋ง ํ์ฉContent-Type
์application/x-www-form-urlencoded
multipart/form-data
text/plain
๋ง ํ์ฉ
GET /data HTTP/1.1
Origin: https://foo.example
๋ธ๋ผ์ฐ์ ๊ฐ ๋ค๋ฅธ ์ถ์ฒ๋ก์ ์์ฒญ์ ๋ณด๋ผ ๋ ์๋์ผ๋ก Origin
ํค๋๋ฅผ ์ถ๊ฐํ์ฌ ๋ณด๋ธ๋ค.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
์๋ฒ๋ Allow-Control-Allow-Origin
ํค๋์ ํ์ฉ๋ Origin ์ ๋ชฉ๋ก์ ๋ด์์ ์๋ตํ๋ค. ์์ผ๋์นด๋๋ฅผ ์ฌ์ฉํด ๋ชจ๋ ์ถ์ฒ๋ฅผ ํ์ฉํ ์๋ ์๋ค.
๋ธ๋ผ์ฐ์ ๋ ์์ฒญ์ Origin
ํค๋์ ๋ด๊ธด ์ถ์ฒ ์ ๋ณด๊ฐ ์๋ต์ Access-Control-Allow-Origin
ํค๋์ ๋ด๊ฒจ์์ผ๋ฉด ํด๋น ์์ฒญ์ ์์ ํ๋ค๊ณ ๊ฐ์ฃผํ๊ณ ์๋ต์ ๊ฐ์ ธ์จ๋ค.
๋ง์ฝ ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ํด๋น ์๋ต์ ์์๋ก ํ๊ธฐํ๊ณ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์๋ต์ ๋ด์ฉ์ ์ ๋ฌํ์ง ์๋๋ค.
Preflight Request
์ค์ ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ ์ OPTIONS
๋ฉ์๋๋ก ์ฌ์ ์์ฒญ์ ๋ณด๋ด์ CORS ํ์ฉ ์ฌ๋ถ๋ฅผ ๋จผ์ ํ์ธํ๋ ๋ฐฉ์์ด๋ค.
OPTIONS /data HTTP/1.1
Origin: https://foo.example
Access-Control-Request-Method: POST
Access-Control-Reqeust-Headers: Content-Type, Custom-Header
Preflight ์์ฒญ์ Simple Request ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ฒญ์ Origin
ํค๋๋ฅผ ์ถ๊ฐํ๊ณ ์ค์ ์์ฒญ์ ๋ฉ์๋๋ฅผ Access-Control-Request-Method
ํค๋์ ๋ด๊ณ ์ค์ ์์ฒญ์ ์ถ๊ฐ ํค๋ ๋ชฉ๋ก์ Access-Control-Request-Headers
ํค๋์ ๋ด์์ ๋ณด๋ธ๋ค.
์ค์ ์์ฒญ ์ด์ ์ ์ด๋ฐ ๋ฉ์๋์ ํค๋๋ก ์์ฒญ์ ๋ณด๋ผ๊ฑด๋ฐ ์๋ฒ CORS ์ ์ฑ ์์ ํ์ฉํ๋์ง ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ์๊ฒ ๋ฏธ๋ฆฌ ๋ฌผ์ด๋ณด๋ ์ ์ฐจ์ด๋ค.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, Custom-Header
Access-Control-Max-Age: 86400
์๋ต ์ญ์ Simple Request ์ ๋ง์ฐฌ๊ฐ์ง๋ก Access-Control-Allow-Origin
ํค๋๊ฐ ๋ด๊ธฐ๊ณ ์๋ฒ์ธก์์ ํ์ฉํ๋ ๋ฉ์๋ ๋ชฉ๋ก์ด ๋ด๊ธด Access-Control-Allow-Methods
ํค๋์ ํ์ฉํ๋ ํค๋ ๋ชฉ๋ก์ด ๋ด๊ธด Access-Control-Allow-Headers
ํค๋ ๊ทธ๋ฆฌ๊ณ Preflight ์ ์บ์ ๊ธฐ๊ฐ์ธ Access-Control-Max-Age
๋ฅผ ๋ณด๋ด์ค๋ค.
Credentialed Request
์ฟ ํค ๋๋ ํ ํฐ๊ณผ ๊ฐ์ด ์ฌ์ฉ์ ์๋ณ ์ ๋ณด๊ฐ ๋ด๊ธด ์์ฒญ์ ๋ํด์๋ ์กฐ๊ธ ๋ ์๊ฒฉํ๊ฒ ์ฒ๋ฆฌํ๋ค.
GET /data HTTP/1.1
Origin: https://foo.example
Cookie: sessionId=123
ํด๋ผ์ด์ธํธ๋ ์์ฒญ์ ๋ณด๋ผ ๋ ์ธ์ฆ์ ๋ณด๋ฅผ ํฌํจํ๊ธฐ ์ํด Credentials ์ต์ ์ ๋ณ๋๋ก ์ค์ ํด์ผํ๋ค. ์ด๋ฌํ ์ค์ ์ ํด์ฃผ์ง ์์ผ๋ฉด ์ฟ ํค ๋ฑ์ ์ธ์ฆ ์ ๋ณด๋ ์ ๋ ์๋์ผ๋ก ์์ฒญ์ ํฌํจ๋์ง ์๋๋ค.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://foo.example
Allow-Control-Allow-Credentials: true
์๋ฒ๋ ์ด๋ฌํ ์์ฒญ์ ๋ํด์ ์ผ๋ฐ์ ์ธ CORS ์์ฒญ๊ณผ ๋ค๋ฅด๊ฒ Access-Control-Allow-Origin
ํค๋์ ๋ช
ํํ Origin ์ ๋ช
์ํด์ฃผ์ด์ผ ํ๋ฉฐ Allow-Control-Allow-Credentials
ํค๋๋ true
๋ก ์ค์ ๋์ด์ผ ํ๋ค.
๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ์ ์ํด ์๋ต์ด ๊ฑฐ๋ถ๋๋ค.
์ ๋ฆฌ
CORS ๋ ์๋ฒ๊ฐ ์๋ ๋ธ๋ผ์ฐ์ ๊ตฌํ ์คํ์ ํฌํจ๋ ์ ์ฑ ์ด๋ค. ๋๋ฌธ์ ์๋ฒ๋ CORS ์๋ฐ ์ฌ๋ถ์ ๊ด๊ณ์์ด ์์ฒญ์ด ๋ค์ด์ค๋ฉด ์ผ๋จ ์ฒ๋ฆฌํ๊ณ ์๋ตํ๋ค. ๊ทธ ์๋ต์ ๋ฐ์์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ต ํค๋๋ฅผ ํ์ธํ๊ณ ์๋ต์ ํ๊ธฐ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋๋ค.
GET
HEAD
์ ๊ฐ์ ๋จ์ ์กฐํ ์์ฒญ์ ์๊ด ์์ด๋ POST
PUT
DELETE
์ ๊ฐ์ ๋ฉ์๋๋ ์๋ฒ์ ๋ถ์์ฉ์ ์ผ๊ธฐํ ์ ์๋ค. ์ด๋ ์๋ต์ด ์ ํจํ์ง ์์ ํ๊ธฐํ ๋ธ๋ผ์ฐ์ ์ ์์ฌ์ ์๊ด์์ด ๋ฐ์ํ๋ค.
Preflight ๋ ์ค์ ์์ฒญ์ด CORS ๋ฅผ ์๋ฐํ์ง ์๋์ง ๋ฏธ๋ฆฌ ํ์ธํ์ฌ ์๋ฒ์ ๋ถ์์ฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ ์กํ๋ค.
ํ์ง๋ง POST
๊ฐ์ ๊ฒฝ์ฐ ์กฐ๊ฑด๋ง ๋ง์กฑํ๋ค๋ฉด Preflight ๋์ Simple Request ๋ก ์ ์ก๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐฑ์๋์์ ์ด์ ๋ํ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.