๐ฅ SOP์ CORS์ ๋ฑ์ฅ ๋ฐฐ๊ฒฝ
๐ฅ Cross-Origin Resource Sharing ๋?
๐ฅ CORS ์๋๋ฆฌ์ค
๐ฅ CORS ์๋ฌ ํด๊ฒฐํ๊ธฐ
โ๏ธ ์น ์ํ๊ณ์๋ ๋ค๋ฅธ ์ถ์ฒ๋ก์ ๋ฆฌ์์ค ์์ฒญ์ ์ ํํ๋ ๊ฒ๊ณผ ๊ด๋ จ๋ ๋ ๊ฐ์ง ์ ์ฑ ์ด ์กด์ฌํ๋ค. ํ ๊ฐ์ง๋ 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, ์ฌ์ดํธ ๊ฐ ์์ฒญ ์์กฐ) : ์ฌ์ฉ์๊ฐ ์์ ์ ์์ง์๋ ๋ฌด๊ดํ๊ฒ ๊ณต๊ฒฉ์๊ฐ ์ด๋ํ ํ์(์์ , ์ญ์ , ๋ฑ๋ก ๋ฑ)๋ฅผ ์น์ฌ์ดํธ์ ์์ฒญํ๊ฒํ๋ ๊ณต๊ฒฉ ํ์
โ๏ธ ์น์ด๋ผ๋ ์ํ๊ณ์์ ๋ค๋ฅธ ์ถ์ฒ์ ์๋ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์์ ์ฌ์ฉํ๋ ์ผ์ ๊ต์ฅํ ํํ ์ผ์ด๊ณ , ์ ์ฐจ ์ด๋ฌํ ํ์์ฑ์ด ์ปค์ง๊ฒ ๋๋ฉด์ SOP์ ์ ์ฑ ์ ๋ณด์์ ํ์์ฑ์ ๊ฐ์ง๊ฒ ๋๋ค.
โ๏ธ ํนํ, SOP๋ก ์ธํด ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ ๋ถํธ์ด ๋ฐ์ํ๋ค. ์ด์ ๋ง์ ๊ฐ๋ฐ์๋ค์ด JONP, Reverse Proxy, Flash Socker ๋ฑ ์ฐํํ๋ ๋ฐฉ๋ฒ์ ๋ง๋ค์์ง๋ง Cross Domain ์ด์๋ฅผ ํด๊ฒฐํ๋ ํ์ค์ ํ์์ฑ์ด ์ปค์ง๊ฒ ๋์๋ค.
โ๏ธ ์ด์ W3C์ ๊ถ์ฅ์ฌํญ์ผ๋ก CORS ์ ์ฑ ์ ๋ฐํํ๊ฒ ๋๋ค.
โ๏ธ ๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (Cross-Origin Resource Sharing, CORS)๋ HTTP๋ฅผ ์ฌ์ฉํ์ฌ, ํ origin์์ ์คํ ์ค์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ origin์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋ ๊ถํ์ ๋ถ์ฌํ๋๋ก ๋ธ๋ผ์ฐ์ ์ ์๋ ค์ฃผ๋ ์ฒด์ ์ด๋ค.
โ๏ธ ์ฆ, ์ฐ๋ฆฌ๊ฐ ๋ค๋ฅธ ์ถ์ฒ๋ก ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๋ค๋ฉด SOP ์ ์ฑ ์ ์๋ฐํ ๊ฒ์ด ๋๊ณ , ๊ฑฐ๊ธฐ๋ค๊ฐ SOP์ ์์ธ ์กฐํญ์ธ CORS ์ ์ฑ ๊น์ง ์งํค์ง ์๋๋ค๋ฉด ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
โ๏ธ ์ด์ SOP ๋๋ CORS ์ ์ฑ ์ ์๊ฑฐํด์ ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ ํด์ง ํค๋๋ฅผ ํตํด ์๋ก ์์ฒญ์ด๋ ์๋ต์ ๋ฐ์ํ ์ง, ์น๋ธ๋ผ์ฐ์ ์ ์ํด ํ๊ฐ๋๊ณ ๊ฒฐ์ ๋๋ค.
โ๏ธ Preflight Request๋ ๋ณธ ์์ฒญ ์ด์ ์ ์ด๋ค์ง๋ ์๋น ์์ฒญ ๊ฐ๋ ์ด๋ค. ์ด ์ฌ์ ์์ฒญ์ OPTIONS๋ผ๋ ๋งค์๋๋ฅผ ํตํด ์ด๋ค์ง๋ค.
โ๏ธ ์ด ์๋น ์์ฒญ์์ request์ origin๊ฐ๊ณผ response์ Access-Control-Allow-Origin์ด ์ผ์นํ๋ฉด, ๋ธ๋ผ์ฐ์ ์์๋ ๊ฐ์ ์ถ์ฒ๋ผ ์ธ์ํด์ ๋ณธ ์์ฒญ์ ๋ณด๋ด๊ฒ ๋๋ค.
โ๏ธ ์ด์ ๋ธ๋ผ์ฐ์ ๋ ๊ฐ์ ์ถ์ฒ๋ผ ์ธ์ํ๊ฒ ๋๋ฉด CORS ์ ์ฑ ์ ์๋ฐ๋์ง ์์๋ค ํ๋จํ๊ณ , ๋ณธ ์์ฒญ์ ์ ๋๋ก๋ ์๋ต์ ๋ฐ์ ์ ์๊ฒ ๋๋ค.
โ๏ธ ๋ง์ผ ์๋น ์์ฒญ์์ origin๊ฐ๊ณผ Access-Control-Allow-Origin๊ฐ์ด ๋ถ์ผ์นํ๋ค๋ฉด ๋ณธ ์์ฒญ์ ์ด๋ค์ง์ง ์๋๋ค.
โ๏ธ Simple Request๋ Preflight Request ์์ฒญ์ด ๋ณ๋๋ก ์กด์ฌํ์ง ์๊ณ , Simple Request ๋ ๋ชจ๋ ํฌํจ๋์ด์๋ ๊ฐ๋ ์ด๋ค.
โ๏ธ ์ด ๋ํ origin๊ณผ Access-Control-Allow-Origin์ ๋น๊ตํด์ ๋์ผ ์ถ์ฒ์ธ์ง ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ํ๋จ๋๊ณ ๋์ผํ ๊ฒฝ์ฐ, ์์ฒญ์ ๋ํ ์๋ต์ ์ฒ๋ฆฌํ๋ค.
โ๏ธ ๋จ, Simple Request๋ HEAD, GET, POST ์ค ํ๋์ ๋ฉ์๋ ์ผ ๋๋ง ์ฌ์ฉ๊ฐ๋ฅํ๊ณ , ์ฌ์ฉํ ์ ์๋ header์ ์ข ๋ฅ๊ฐ ์ ํ์ ์ด๋ค. ํนํ, Content-Type์ผ๋ก application/json์ ์ฌ์ฉํ ์ ์๋ค.
โ๏ธ 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๊ฐ ์กด์ฌํด์ผ ํ๋ค.
โ๏ธ ํ์ฌ ํ๋ก ํธ ์์ ์ด ํ๋ก ํธ ์ ์ฅ์ด๊ฑฐ๋, ํด๋น ์๋ฒ๋ฅผ ์ ์ดํ ์ ์๋ ์ํฉ์ด๋ผ๋ฉด ํ๋ก์ ์๋ฒ๋ฅผ ์ด์ฉํด์ CORS ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค.
โ๏ธ ์ด๋ฅผ ์ํด ๋จ์ด ๋ง๋ ๋ง๋ค์ด์ง ํ๋ก์ ์๋ฒ๋ฅผ ์ด์ฉํ๊ฑฐ๋ ์ง์ ํ๋ก์ ์๋ฒ๋ฅผ ๊ตฌ์ถํด์ผ ํ๋ค.
โ๏ธ ์ฆ, ์ด ์ค๊ณ์๋ฒ๋ฅผ ์ด์ฉํด์ ์์ฒญ์ ๊ฐ๋ก์ฑ ๋ค, Access-Control-Allow-Origin : *
์ ์ค์ ํด์ ์๋ฒ์ ์์ฒญ๋๊ฒ ํ๋ ๊ฒ์ด๋ค.
โ๏ธ 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์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค๋ ์ด์๋ฅผ ๋ณธ์ ์ด ์์ด ๊ฐ๋ตํ๊ฒ ์ ๋ฆฌํด๋ณธ๋ค.
โ๏ธ ์ด ์ด์๋ฅผ ์์ฝํด๋ณด๋ฉด, 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; # ๐ ์ฌ์ง ์ฌ์ด์ฆ ์ ํ ๋ณ๊ฒฝ }