TIL102. HTTP : Cross-Origin Resource Sharing

ID์งฑ์žฌยท2021๋…„ 12์›” 26์ผ
0

HTTP

๋ชฉ๋ก ๋ณด๊ธฐ
16/17
post-thumbnail
post-custom-banner

๐ŸŒˆ CORS ๋ž€?

๐Ÿ”ฅ SOP์™€ CORS์˜ ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

๐Ÿ”ฅ Cross-Origin Resource Sharing ๋ž€?

๐Ÿ”ฅ CORS ์‹œ๋‚˜๋ฆฌ์˜ค

๐Ÿ”ฅ CORS ์—๋Ÿฌ ํ•ด๊ฒฐํ•˜๊ธฐ



1. SOP์™€ CORS์˜ ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

๐Ÿค” ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(Same-Origin Policy) ๋ž€?

โœ”๏ธ ์›น ์ƒํƒœ๊ณ„์—๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ์˜ ๋ฆฌ์†Œ์Šค ์š”์ฒญ์„ ์ œํ•œํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ๋œ ๋‘ ๊ฐ€์ง€ ์ •์ฑ…์ด ์กด์žฌํ•œ๋‹ค. ํ•œ ๊ฐ€์ง€๋Š” CORS, ๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•œ ๊ฐ€์ง€๋Š” SOP(Same-Origin Policy)์ด๋‹ค.

โœ”๏ธ ์ด ์ค‘ SOP๋Š” 2011๋…„, RFC 6454์—์„œ ์ฒ˜์Œ ๋“ฑ์žฅํ•œ ๋ณด์•ˆ ์ •์ฑ…์œผ๋กœ ๋ง ๊ทธ๋Œ€๋กœ โ€œ๊ฐ™์€ ์ถœ์ฒ˜์—์„œ๋งŒ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹คโ€๋ผ๋Š” ๊ทœ์น™์„ ๊ฐ€์ง„ ์ •์ฑ…์ด๋‹ค.

โœ”๏ธ ๊ฐ™์€ ์ถœ์ฒ˜์™€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์— ๋Œ€ํ•ด์„œ๋Š” ์ด๋ฏธ ์ •๋ฆฌ(์ฐธ๊ณ  : Same Origin)ํ•ด ๋‘์—ˆ๋‹ค.

โœ”๏ธ ์ด์— ๋”ฐ๋ผ SOP๋Š” ์–ด๋–ค ์ถœ์ฒ˜(origin)์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฌธ์„œ๋‚˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ์ž‘์šฉ ํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œ์‹œํ‚ค๋Š” ์ค‘์š”ํ•œ ๋ณด์•ˆ ๋ฐฉ์‹์ด๋‹ค.

โœ”๏ธ SOP ์ •์ฑ…์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ํ†ต์‹ ํ•จ์— ์žˆ์–ด์„œ XSS๋‚˜ XSRF ๋“ฑ์˜ ๋ณด์•ˆ ์ทจ์•ฝ์ ์„ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

  • XSS(Cross Site Scription, ์‚ฌ์ดํŠธ ๊ฐ„ ์Šคํฌ๋ฆฝํŒ…) : ๊ด€๋ฆฌ์ž๊ฐ€ ์•„๋‹Œ ๊ถŒํ•œ์ด ์—†๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์›น ์‚ฌ์ดํŠธ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ณต๊ฒฉ ํ–‰์œ„
  • XSRF(Cross Site Request Forgery, ์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ) : ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ์˜์ง€์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์ด๋„ํ•œ ํ–‰์œ„(์ˆ˜์ •, ์‚ญ์ œ, ๋“ฑ๋ก ๋“ฑ)๋ฅผ ์›น์‚ฌ์ดํŠธ์— ์š”์ฒญํ•˜๊ฒŒํ•˜๋Š” ๊ณต๊ฒฉ ํ–‰์œ„

๐Ÿค” CORS ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

โœ”๏ธ ์›น์ด๋ผ๋Š” ์ƒํƒœ๊ณ„์—์„œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์— ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•˜๋Š” ์ผ์€ ๊ต‰์žฅํžˆ ํ”ํ•œ ์ผ์ด๊ณ , ์ ์ฐจ ์ด๋Ÿฌํ•œ ํ•„์š”์„ฑ์ด ์ปค์ง€๊ฒŒ ๋˜๋ฉด์„œ SOP์˜ ์ •์ฑ…์€ ๋ณด์™„์˜ ํ•„์š”์„ฑ์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.

โœ”๏ธ ํŠนํžˆ, SOP๋กœ ์ธํ•ด ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ•˜๋Š” ๋ถˆํŽธ์ด ๋ฐœ์ƒํ•œ๋‹ค. ์ด์— ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด JONP, Reverse Proxy, Flash Socker ๋“ฑ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งŒ๋“ค์—ˆ์ง€๋งŒ Cross Domain ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํ‘œ์ค€์˜ ํ•„์š”์„ฑ์ด ์ปค์ง€๊ฒŒ ๋˜์—ˆ๋‹ค.

โœ”๏ธ ์ด์— W3C์˜ ๊ถŒ์žฅ์‚ฌํ•ญ์œผ๋กœ CORS ์ •์ฑ…์„ ๋ฐœํ‘œํ•˜๊ฒŒ ๋œ๋‹ค.



2. Cross-Origin Resource Sharing ๋ž€?

๐Ÿค” Cross-Origin Resource Sharing

โœ”๏ธ ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resource Sharing, CORS)๋Š” HTTP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ํ•œ origin์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ origin์˜ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ์ด๋‹ค.

โœ”๏ธ ์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•œ๋‹ค๋ฉด SOP ์ •์ฑ…์„ ์œ„๋ฐ˜ํ•œ ๊ฒƒ์ด ๋˜๊ณ , ๊ฑฐ๊ธฐ๋‹ค๊ฐ€ SOP์˜ ์˜ˆ์™ธ ์กฐํ•ญ์ธ CORS ์ •์ฑ…๊นŒ์ง€ ์ง€ํ‚ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

โœ”๏ธ ์ด์— SOP ๋˜๋Š” CORS ์ •์ฑ…์— ์˜๊ฑฐํ•ด์„œ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ •ํ•ด์ง„ ํ—ค๋”๋ฅผ ํ†ตํ•ด ์„œ๋กœ ์š”์ฒญ์ด๋‚˜ ์‘๋‹ต์— ๋ฐ˜์‘ํ• ์ง€, ์›น๋ธŒ๋ผ์šฐ์ €์— ์˜ํ•ด ํ‰๊ฐ€๋˜๊ณ  ๊ฒฐ์ •๋œ๋‹ค.



3. CORS ์‹œ๋‚˜๋ฆฌ์˜ค

๐Ÿค” Preflight Request

โœ”๏ธ Preflight Request๋Š” ๋ณธ ์š”์ฒญ ์ด์ „์— ์ด๋ค„์ง€๋Š” ์˜ˆ๋น„ ์š”์ฒญ ๊ฐœ๋…์ด๋‹ค. ์ด ์‚ฌ์ „ ์š”์ฒญ์€ OPTIONS๋ผ๋Š” ๋งค์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ด๋ค„์ง„๋‹ค.

โœ”๏ธ ์ด ์˜ˆ๋น„ ์š”์ฒญ์—์„œ request์˜ origin๊ฐ’๊ณผ response์˜ Access-Control-Allow-Origin์ด ์ผ์น˜ํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ๊ฐ™์€ ์ถœ์ฒ˜๋ผ ์ธ์‹ํ•ด์„œ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค.

โœ”๏ธ ์ด์— ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ฐ™์€ ์ถœ์ฒ˜๋ผ ์ธ์‹ํ•˜๊ฒŒ ๋˜๋ฉด CORS ์ •์ฑ…์— ์œ„๋ฐ˜๋˜์ง€ ์•Š์•˜๋‹ค ํŒ๋‹จํ•˜๊ณ , ๋ณธ ์š”์ฒญ์— ์ œ๋Œ€๋กœ๋œ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

โœ”๏ธ ๋งŒ์ผ ์˜ˆ๋น„ ์š”์ฒญ์—์„œ origin๊ฐ’๊ณผ Access-Control-Allow-Origin๊ฐ’์ด ๋ถˆ์ผ์น˜ํ•˜๋‹ค๋ฉด ๋ณธ ์š”์ฒญ์€ ์ด๋ค„์ง€์ง€ ์•Š๋Š”๋‹ค.

๐Ÿค” Simple Request

โœ”๏ธ Simple Request๋Š” Preflight Request ์š”์ฒญ์ด ๋ณ„๋„๋กœ ์กด์žฌํ•˜์ง€ ์•Š๊ณ , Simple Request ๋•Œ ๋ชจ๋‘ ํฌํ•จ๋˜์–ด์žˆ๋Š” ๊ฐœ๋…์ด๋‹ค.

โœ”๏ธ ์ด ๋˜ํ•œ origin๊ณผ Access-Control-Allow-Origin์„ ๋น„๊ตํ•ด์„œ ๋™์ผ ์ถœ์ฒ˜์ธ์ง€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ํŒ๋‹จ๋˜๊ณ  ๋™์ผํ•  ๊ฒฝ์šฐ, ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

โœ”๏ธ ๋‹จ, Simple Request๋Š” HEAD, GET, POST ์ค‘ ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ ์ผ ๋•Œ๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๊ณ , ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” header์˜ ์ข…๋ฅ˜๊ฐ€ ์ œํ•œ์ ์ด๋‹ค. ํŠนํžˆ, Content-Type์œผ๋กœ application/json์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

๐Ÿค” Credentialed Request

โœ”๏ธ Credentialed Request๋Š” ๋ณด๋‹ค ๋ณด์•ˆ์„ ๊ฐ•ํ™”์‹œํ‚จ ๋ฐฉ์‹์œผ๋กœ ์ฟ ๊ธฐ๋ฅผ ๋‹ด๊ธฐ ์œ„ํ•ด ์˜ต์…˜์ด๋‹ค. ์ด ์˜ต์…˜์œผ๋กœ same-origin(๊ธฐ๋ณธ๊ฐ’), include, omit์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

โœ”๏ธ same-origin์€ ๊ฐ™์€ ์ถœ์ฒ˜ ๊ฐ„ ์š”์ฒญ์—๋งŒ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด๊ฒ ๋‹ค๋Š” ์˜ต์…˜ ๊ฐ’์ด๊ณ , include๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. omit์€ ๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

โœ”๏ธ ์ฐธ๊ณ ๋กœ ์œ„ ์˜ต์…˜๊ฐ’๋“ค์€ fetch๋ฅผ ์ค„ ๋•Œ, ์‚ฌ์šฉํ•˜๋Š” ์˜ต์…˜์ด๋‹ค.

fetch('https://jaewon.com/products/1', { credentials: 'include'})

โœ”๏ธ ๋‹จ, Access-Control-Allow-Origin์— *์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ , ๋ช…์‹œ์ ์ธ URL์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ ์‘๋‹ต header์— Access-Control-Allow-Credentails:true๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.



4. CORS ์—๋Ÿฌ ํ•ด๊ฒฐํ•˜๊ธฐ

๐Ÿค” ํ”„๋ก์‹œ ์„œ๋ฒ„ ์‚ฌ์šฉํ•˜๊ธฐ

โœ”๏ธ ํ˜„์žฌ ํ”„๋ก ํŠธ ์ž์‹ ์ด ํ”„๋ก ํŠธ ์ž…์žฅ์ด๊ฑฐ๋‚˜, ํ•ด๋‹น ์„œ๋ฒ„๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ํ”„๋ก์‹œ ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•ด์„œ CORS ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.

โœ”๏ธ ์ด๋ฅผ ์œ„ํ•ด ๋‚จ์ด ๋งŒ๋“  ๋งŒ๋“ค์–ด์ง„ ํ”„๋ก์‹œ ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•˜๊ฑฐ๋‚˜ ์ง์ ‘ ํ”„๋ก์‹œ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•ด์•ผ ํ•œ๋‹ค.

โœ”๏ธ ์ฆ‰, ์ด ์ค‘๊ณ„์„œ๋ฒ„๋ฅผ ์ด์šฉํ•ด์„œ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑˆ ๋’ค, Access-Control-Allow-Origin : * ์„ ์„ค์ •ํ•ด์„œ ์„œ๋ฒ„์— ์š”์ฒญ๋˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๐Ÿค” django์—์„œ cross origin HTTP ์š”์ฒญ์„ ํ—ˆ๊ฐ€์‹œํ‚ค๊ธฐ

โœ”๏ธ pip install๋กœ django-cors-headers ์•ฑ์„ ์„ค์น˜ํ•œ๋‹ค.

โœ”๏ธ installed apps๊ณผ middleware์— ์•„๋ž˜ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ ํ•œ๋‹ค. ์ค‘์š”ํ•œ ์ ์€ middleware์— cors ์„ค์ •์„ ๊ฐ€์žฅ ๋†’๊ฒŒ ์œ„์น˜์‹œํ‚จ๋‹ค.

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware', # < ๊ฐ€๋Šฅํ•œํ•œ ๋†’๊ฒŒ ์œ„์น˜์‹œํ‚จ๋‹ค.
    ...
]

โœ”๏ธ ์•„๋ž˜๋Š” ๋ชจ๋“  ํ˜ธ์ŠคํŠธ๋ฅผ ํ—ˆ์šฉ์‹œํ‚ค๊ธฐ ์œ„ํ•ด CORS_ORIGIN_ALLOW_ALL์„ True๋กœ ์ง€์ •ํ•œ ๊ฒƒ์ด๋‹ค.

โœ”๏ธ CORS_ALLOW_CREDENTIALS์€ ์ฟ ํ‚ค๊ฐ€ cross-site HTTP ์š”์ฒญ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๊ฒŒํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •์ด๊ณ  Default๋Š” False๋‹ค.

##CORS
CORS_ORIGIN_ALLOW_ALL=True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_METHODS = ( # ๐Ÿ‘ˆ custom method๊ฐ€ ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ ์ถ”๊ฐ€ํ•œ๋‹ค.
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
)
CORS_ALLOW_HEADERS = (  # ๐Ÿ‘ˆ custom header๊ฐ€ ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ ์ถ”๊ฐ€ํ•œ๋‹ค.
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

โœ”๏ธ ๋ชจ๋“  ํ˜ธ์ŠคํŠธ๊ฐ€ ์•„๋‹Œ, ํŠน์ • ํ˜ธ์ŠคํŠธ๋ฅผ ํ—ˆ์šฉ์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๋ฉด CORS_ORIGIN_WHITELIST๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

##CORS
CORS_ORIGIN_WHITELIST = (
    "https://example.com",
    "https://sub.example.com",
    "http://localhost:8080",
    "http://127.0.0.1:9000"
)
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
)
CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

๐Ÿค” nginx์—์„œ CORS ์„ค์ •์„ ํ†ตํ•ด error ํ•ด๊ฒฐ

โœ”๏ธ ์šฉ๋Ÿ‰์ด ํฐ ์‚ฌ์ง„์„ ์—…๋กœ๋“œํ•  ๊ฒฝ์šฐ, nginx์—์„œ CORS์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๋Š” ์ด์Šˆ๋ฅผ ๋ณธ์ ์ด ์žˆ์–ด ๊ฐ„๋žตํ•˜๊ฒŒ ์ •๋ฆฌํ•ด๋ณธ๋‹ค.

โœ”๏ธ ์ด ์ด์Šˆ๋ฅผ ์š”์•ฝํ•ด๋ณด๋ฉด, nginx์—์„œ client_max_body_size๊ฐ€ 1mb๋กœ ์ œํ•œ๋˜์–ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ผ๊ณ  ํ•œ๋‹ค.

โœ”๏ธ nginx๊ฐ€ ์„ค์น˜๋œ ํด๋” ์•ˆ์— conf/nginx.conf ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.

location / {
    #root   html;
    root e:/;
    add_header 'Access-Control-Allow-Origin' '*'; # ๐Ÿ‘ˆ cors ํ—ˆ์šฉ ์ถ”๊ฐ€
    index  index.html index.htm;
}
http {
    ...
    client_max_body_size 20M; # ๐Ÿ‘ˆ ์‚ฌ์ง„ ์‚ฌ์ด์ฆˆ ์ œํ•œ ๋ณ€๊ฒฝ
}    
profile
Keep Going, Keep Coding!
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€