๐Ÿ’ก CORS๋ฅผ ํ•™์Šตํ•ด ๋ณด์ž

5379 ๋‹จ์–ด webTILTIL

CORS

CORS๋ž€?

SOP์˜ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ CORS ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์„ค๋ช…ํ•œ ์‚ฌ์ง„

  • Cross-Origin Resource Sharing (๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ )
  • ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ
  • ์ถœ์ฒ˜๋Š” ๋„๋ฉ”์ธ, ํ”„๋กœํ† ์ฝœ, ํฌํŠธ๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•จ์„ ๋œปํ•จ
  • ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ… (SOP) ๋กœ ์ธํ•ด ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๊ฐ„ ์ž์›(๋ฐ์ดํ„ฐ) ์ด๋™์ด ๊ธˆ์ง€

SOP (Same-Origin Policy)

CORS๋ฅผ ์•Œ์•„๋ณด๊ธฐ ์ „ ๋จผ์ € SOP์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž

  • ๊ต์ฐจ ์ถœ์ฒ˜ ์ •์ฑ…์œผ๋กœ ์–ด๋–ค ์ถœ์ฒ˜์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฌธ์„œ๋‚˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œํ•จ
  • XMLHttpRequest(fetch() ์™€ ๊ฐ™์€)์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ƒํ˜ธ์ž‘์šฉ์„ ํ†ต์ œ
    • Chrome์˜ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ Fetch/XHR ํ•ญ๋ชฉ

SOP, CORS์—์„œ Origin (์ถœ์ฒ˜) ์ด๋ž€?

  • ์ถœ์ฒ˜๋Š” Protocol, Host, Port๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•  ๋•Œ ๋™์ผ ์ถœ์ฒ˜๋ผ๊ณ  ํ•œ๋‹ค.
  • ์œ„์˜ ์˜ˆ์‹œ์—์„œ https๋Š” 443ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค.
  • https://velog.io:443/@k-moovie ๋Š” ๋™์ผ ์ถœ์ฒ˜์ด๋‹ค

CORS๋ž€?

  • ์›น ๊ธฐ์ˆ ์ด ๋ฐœ์ „ํ•จ์— ๋”ฐ๋ผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์˜ ์ž์›(์ด๋ฏธ์ง€์™€ ๊ฐ™์€)์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์›น ํด๋ผ์ด์–ธํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ๋Š” HTTP ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ request๋ฅผ ๋ณด๋‚ธ๋‹ค

  • ์ด ๋•Œ ๋ธŒ๋ผ์šฐ์ €๋Š” request header์˜ Originํ•„๋“œ์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ถœ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋‹ด์•„ ๋ณด๋‚ธ๋‹ค.

    Origin: https://velog.io/@k-moovie

  • ์ดํ›„ ์„œ๋ฒ„์—์„œ ์‘๋‹ต์„ ๋ณด๋‚ผ ๋•Œ response header์˜ Access-Control-Allow-Origin ํ•„๋“œ์— '์ด ๋ฆฌ์†Œ์Šค๋ฅผ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด ํ—ˆ์šฉ๋œ ์ถœ์ฒ˜'๋ฅผ ์ „์†กํ•œ๋‹ค.

  • ๋ธŒ๋ผ์šฐ์ €๋Š” ์ž์‹ ์ด ๋ณด๋‚ธ Origin๊ณผ ์„œ๋ฒ„์—์„œ ์˜จ ์‘๋‹ต์˜ Access-Control-Allow-Origin๋ฅผ ๋น„๊ตํ•ด ๊ฐ™๋‹ค๋ฉด ํ—ˆ์šฉํ•œ๋‹ค.

CORS์˜ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค

Preflight Request

  • ์ผ๋ฐ˜์ ์œผ๋กœ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ ํ”ํžˆ ๋งˆ์ฃผํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค
  • ์˜ˆ๋น„ ์š”์ฒญ๊ณผ ๋ณธ ์š”์ฒญ์œผ๋กœ ๋‘ ๋ฒˆ ์ „์†ก

OPTIONS https://velog.io/@k-moovie

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: velog.io
Origin: https://velog.io
Referer: https://velog.io/@k-moovie/user
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
  • ์˜ˆ๋น„ ์š”์ฒญ์€ method๊ฐ€ OPTIONS๋กœ ์ „์†ก๋œ๋‹ค
    • ๋ณธ ์š”์ฒญ์— ์‚ฌ์šฉํ•  ๋‹ค๋ฅธ ์ •๋ณด๋ฅผ (method, header ๋“ฑ) ๊ฐ™์ด ์ „์†กํ•œ๋‹ค.
OPTIONS https://velog.io/@k-moovie 200 OK

Access-Control-Allow-Origin: https://velog.io
Content-Encoding: gzip
Content-Length: 699
Content-Type: text/xml; charset=utf-8
Date: Sun, 24 May 2020 11:52:33 GMT
P3P: CP='ALL DSP COR MON LAW OUR LEG DEL'
Server: Apache
Vary: Accept-Encoding
X-UA-Compatible: IE=Edge
  • ์„œ๋ฒ„๋Š” ์˜ˆ๋น„ ์š”์ฒญ์˜ ์‘๋‹ต์œผ๋กœ Access-Control-Allow-Origin์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Simple Request

  • ์„œ๋ฒ„์— ๊ณง๋ฐ”๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์œผ๋กœ ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์š”์ฒญ์„ ๊ฐ€๋ฆฌ์ง€ ์•Š์œผ๋ฏ€๋กœ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค
  • Preflight Request์—์„œ ์˜ˆ๋น„ ์š”์ฒญ์„ ์ œ๊ฑฐํ•œ ๊ฒƒ
  • ์•„๋ž˜์˜ ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ๋‹ค
    • ์š”์ฒญ์˜ ๋ฉ”์†Œ๋“œ๋Š” GET, HEAD, POST ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.
    • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width๋ฅผ ์ œ์™ธํ•œ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
    • Content-Type๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” application/x-www-form-urlencoded, multipart/form-data, text/plain๋งŒ ํ—ˆ์šฉ๋œ๋‹ค.

Credentialed Request

  • ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๊ฐ„ ํ†ต์‹ ์—์„œ ์ข€ ๋” ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋น„๋™๊ธฐ ๋ฆฌ์†Œ์Šค ์š”์ฒญ API์ธ XMLHttpRequest ๊ฐ์ฒด๋‚˜ fetch API๋Š” ๋ณ„๋„์˜ ์˜ต์…˜ ์—†์ด ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟ ํ‚ค ์ •๋ณด๋‚˜ ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ํ—ค๋”๋ฅผ ํ•จ๋ถ€๋กœ ์š”์ฒญ์— ๋‹ด์ง€ ์•Š๋Š”๋‹ค
  • ์š”์ฒญ์— ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์˜ต์…˜์ด ๋ฐ”๋กœ credentials ์˜ต์…˜
  • ์•„๋ž˜์™€ ๊ฐ™์€ ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ๋‹ค
    • Access-Control-Allow-Origin์—๋Š” *๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ๋ช…์‹œ์ ์ธ URL์ด์–ด์•ผํ•œ๋‹ค.
    • ์‘๋‹ต ํ—ค๋”์—๋Š” ๋ฐ˜๋“œ์‹œ Access-Control-Allow-Credentials: true๊ฐ€ ์กด์žฌํ•ด์•ผํ•œ๋‹ค.

๋” ์•Œ์•„๋ณด๊ธฐ

Spring์—์„œ CORS๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

  • Servlet Filter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปค์Šคํ…€ํ•œ Cors ์„ค์ •
  • WebMvcConfiguer๋ฅผ ๊ตฌํ˜„ํ•œ Configuration ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ addCorsMappings()๋ฅผ ์žฌ์ •์˜
  • Spring Security์—์„œ CorsConfigurationSource๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  config์— ์ถ”๊ฐ€

Reference

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ