[๋„คํŠธ์›Œํฌ] ๐Ÿ“š CORS ์ดํ•ดํ•˜๊ธฐ

ํ—Œ์น˜ยท2022๋…„ 7์›” 30์ผ
3

๋„คํŠธ์›Œํฌ

๋ชฉ๋ก ๋ณด๊ธฐ
2/4
post-thumbnail

๐Ÿ“–์‚ฌ์ „ ๊ฐœ๋…

1. Origin(์ถœ์ฒ˜)

image

URL์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ, ํฌํŠธ ๊ฐ€ ๊ฐ™์„ ๋•Œ ๊ฐ™์€ ์ถœ์ฒ˜!

  • localhost ์™€ 127.0.0.1์€ ๋‹ค๋ฅธ ํ˜ธ์ŠคํŠธ๋กœ ํŒ๋‹จ๋จ!(์‹ค์ œ๋กœ๋Š” ๊ฐ™์€ ์ฃผ์†Œ์ง€๋งŒ)

2. SOP(Same Origin Policy)

image

์ •์˜

  • ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ๋ฐฉ์‹

์™œ SOP๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€?

  • ์ธ์Šคํƒ€๊ทธ๋žจ ๋กœ๊ทธ์ธ ํ›„ ํ•ด์ปค ๋งํฌ ํด๋ฆญ ์‹œ
    • ํ•ด์ปค๊ฐ€ ์ธ์Šคํƒ€๊ทธ๋žจ ํ† ํฐ์„ ํ†ตํ•ด ๊ฒŒ์‹œ๋ฌผ์„ ๋งˆ์Œ๋Œ€๋กœ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค!
    • ์†ก๊ธˆ ๋“ฑ ๋ฏผ๊ฐ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค!
  • SOP๋ฅผ ์ด์šฉํ•˜๋ฉด Origin์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์š”์ฒญ์„ ๊ฑฐ์ ˆํ•œ๋‹ค!
    • (ํ•ด์ปค๋Š” hacker.ck์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. ์›๋ž˜๋Š” instagram.com์—์„œ ์š”์ฒญ์ด ์™€์•ผ ํ•œ๋‹ค!)

๐Ÿ  CORS

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resorce Sharing, CORS)

1. ์ •์˜

๋‹ค๋ฅธ Origin(๋„๋ฉ”์ธ/ํ”„๋กœํ† ์ฝœ..) ๋“ฑ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ํ—ˆ์šฉํ•ด์ฃผ๋Š” ๊ฒƒ!

์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•ด ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด
๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ!

2. ์ ‘๊ทผ ์ œ์–ด ์‹œ๋‚˜๋ฆฌ์˜ค

1) Simple Request

์‚ฌ์ „์š”์ฒญ(Preflight) ์—†์ด! ๋ฐ”๋กœ ์š”์ฒญ์„ ๋‚ ๋ฆผ!

ํ•„์š”์กฐ๊ฑด

  1. GET, POST, HEAD ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•จ
  2. ํ—ค๋”๋Š” ๋‹ค์Œ๋งŒ ํ—ˆ์šฉ๋จ!
Accept
Accept-Language
Content-Language
Content-Type
  • WebKit/Safari ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฒฝ์šฐ
    • ํ—ค๋” ์ค‘ ํ•˜๋‚˜์— nonstandard ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด,
    • ๋” ์ด์ƒ ์š”์ฒญ์„ simple request๋กœ ๊ฐ„์ฃผํ•˜์ง€ ์•Š๋Š”๋‹ค!
  1. POST ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ, Content-Type(์š”์ฒญ ๋ฐ”๋”” ํƒ€์ž…)์ด ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•จ
application/x-www-form-urlencoded
multipart/form-data
text/plain

2) Preflight Request

image

๋„ˆ๋„ค ์ง‘์— ๋†€๋Ÿฌ๊ฐ€๋„ ๋ผ?

๋ณธ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „, ์š”์ฒญ์„ ๋ณด๋‚ด๋„ ๋˜๋Š”์ง€ Options ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธ

๊ณผ์ •

  1. ์‚ฌ์ „ ์š”์ฒญ(preflight request)๋กœ ์ด ์š”์ฒญ์„ ๋ณด๋‚ด๋„ ๋˜๋Š”์ง€ ๋ฌผ์–ด๋ด„. ํ—ค๋”์— ๋‹ค์Œ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด์•ผ ํ•จ
"Origin" : ํ•ด๋‹น ์œ„์น˜์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๋Š” ๋œป
"Access-Control-Request-Method" : ์–ด๋–ค ๋ฉ”์†Œ๋“œ์˜ ์š”์ฒญ์„ ๋ณด๋‚ผ๊ฑด์ง€ ๋ฌผ์–ด๋ด„
"Access-Control-Request-Headers" : ์‹ค์ œ ์š”์ฒญ์— ์ถ”๊ฐ€ ํ—ค๋”๋ฅผ ๋ฌด์—‡์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ฌผ์–ด๋ด„
  1. ๋ณด๋‚ด๋„ ๋œ๋‹ค๋Š” ์‚ฌ์ „ ์‘๋‹ต(preflight response)์„ ๋ฐ›๋Š”๋‹ค. ์ด๋•Œ ํ—ค๋”์— ๋‹ค์Œ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด์•ผ ํ•จ
"Access-Control-Allow-Origin" : ํ•ด๋‹น `Origin`์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป
"Access-Control-Allow-Methods" : ํ•ด๋‹น `๋ฉ”์†Œ๋“œ`๋“ค์˜ ์š”์ฒญ์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป
"Access-Control-Allow-Headers" : ํ•ด๋‹น `ํ—ค๋”`๋“ค์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป
"Access-Control-Max-Age" : ์‘๋‹ต์˜ `์บ์‹œ` ๊ธฐ๊ฐ„, ํ•ด๋‹น ์บ์‹œ๊ฐ€ ์žˆ์„์‹œ preflight ๊ณผ์ •์„ ๊ฑด๋„ˆ๋œ€
  • ๋‹ค์Œ ์กฐ๊ฑด์ด ํ•„์š”ํ•จ
    1. ์‘๋‹ต์€ 200๋Œ€
    2. ์‘๋‹ต ๋ฐ”๋””๋Š” ๋น„์–ด์žˆ์Œ
  1. ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋ƒ„~
  2. ์‹ค์ œ ์‘๋‹ต์„ ๋ฐ›์Œ~

3) Credentialed Request

์ž๊ฒฉ์ฆ๋ช…(์ฟ ํ‚ค, authorization, ์ธ์ฆ์„œ..)๋ฅผ ํฌํ•จํ•˜๋Š” ์š”์ฒญ

2)์™€ ๊ฐ™์€ ์‚ฌ์ „์š”์ฒญ(preflight request)์„ ๋ณด๋‚ธ๋‹ค.
์ด๋•Œ ์‚ฌ์ „ ์š”์ฒญ-์‘๋‹ต ํ—ค๋” ํ•„๋“œ๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค.

๊ณผ์ •

  1. ์‚ฌ์ „ ์š”์ฒญ(preflight)๋กœ ์ด ์š”์ฒญ์„ ๋ณด๋‚ด๋„ ๋˜๋Š”์ง€ ๋ฌผ์–ด๋ด„. ์ด๋•Œ ํ—ค๋”์— ๋‹ค์Œ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด์•ผ ํ•จ
"Origin" : ํ•ด๋‹น ์œ„์น˜์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๋Š” ๋œป
"credentials : include" : ์ž๊ฒฉ์ฆ๋ช… ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ๋‹ค๋Š” ๋œป
์ž๊ฒฉ์ฆ๋ช… ์ •๋ณด : ํ—ค๋”๋‚˜ ์ฟ ํ‚ค ๋“ฑ
  1. ๋ณด๋‚ด๋„ ๋œ๋‹ค๋Š” ์‘๋‹ต์„ ๋ฐ›์Œ. ์ด๋•Œ ํ—ค๋”์— ๋‹ค์Œ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด์•ผ ํ•จ
"Access-Control-Allow-Origin" : ํ•ด๋‹น `Origin`์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป
"Access-Control-Allow-Credentials: true" : ์ž๊ฒฉ์ฆ๋ช…์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ๋œป
  1. ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋ƒ„~
  2. ์‹ค์ œ ์‘๋‹ต์„ ๋ฐ›์Œ~

์ฃผ์˜์‚ฌํ•ญ

์ž๊ฒฉ์ฆ๋ช… ์š”์ฒญ์˜ ์‘๋‹ต์€

  • ์„œ๋ฒ„๋Š”Access-Control-Allow-Originํ—ค๋” ๊ฐ’์—
  • "*" ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์—†๊ณ , ๋ฐ˜๋“œ์‹œ ์ถœ์ฒ˜๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•จ!

4) ์ถ”๊ฐ€ ํ—ค๋”

Access-Control-Expose-Headers : ์›น ๋ธŒ๋ผ์šฐ์ €์˜ ํด๋ผ์ด์–ธํŠธ ์Šคํฌ๋ฆฝํŠธ์— ๋…ธ์ถœ๋  ํ—ค๋”๋ฅผ ๊ฒฐ์ •ํ•จ

3. ์Šคํ”„๋ง๋ถ€ํŠธ ์ ์šฉ ๋ฐฉ์‹

    private static final String ALLOWED_METHOD_NAMES = "GET,HEAD,POST,DELETE,TRACE,OPTIONS,PATCH,PUT";

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://{ํ”„๋ก ํŠธ public ip}", "http://{๋„๋ฉ”์ธ}"
                , "http://www.{๋„๋ฉ”์ธ}", "https://{๋„๋ฉ”์ธ}", "https://www.{๋„๋ฉ”์ธ}")
                .allowedMethods(ALLOWED_METHOD_NAMES.split(","))
                .allowCredentials(true)
                .exposedHeaders(HttpHeaders.LOCATION)
                .exposedHeaders(HttpHeaders.AUTHORIZATION);
    }
  • ๋ชจ๋“  URL์—์„œ
    • ํŠน์ • ์˜ค๋ฆฌ์ง„์˜ ๊ฒฝ์šฐ
    • ALLOWED_METHOD_NAMES ์— ํ•ด๋‹นํ•˜๋Š” HTTP ๋ฉ”์†Œ๋“œ์ธ ๊ฒฝ์šฐ
    • ์ž๊ฒฉ์ฆ๋ช… ํ•„๋“œ๋ฅผ ํ—ˆ์šฉํ•ด์ฃผ๊ณ 
    • exposedHeaders ๋กœ ํด๋ผ์ด์–ธํŠธ ์Šคํฌ๋ฆฝํŠธ์— ๋„˜๊ฒจ์ค„ ํ—ค๋”๋“ค์„ ์„ค์ •ํ•œ๋‹ค!

๐Ÿ“š ์ฐธ๊ณ ์ž๋ฃŒ


๐Ÿ“ฎ ์งˆ๋ฌธ ๋ฆฌ์ŠคํŠธ

1. SOP ๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์™œ ํ•„์š”ํ•œ์ง€ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

  1. sop๋Š” same origin policy์˜ ์•ฝ์ž๋กœ, url๋กœ ํ™•์ธ ๊ฐ€๋Šฅํ•œ Origin์ด ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ ์ œํ•œํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์ •์ฑ…์ž…๋‹ˆ๋‹ค.
  2. ์ฆ‰ ๊ฐ™์€ ์˜ค๋ฆฌ์ง„(์ถœ์ฒ˜)์—์„œ ์˜จ ์š”์ฒญ์ด์–ด์•ผ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ •์ƒ์ ์œผ๋กœ ์‘๋‹ต์„ ๋ณด์—ฌ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  3. ์ด๋Š” ๋ณด์•ˆ์„ ์œ„ํ•ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    1. ์˜ˆ๋ฅผ๋“ค์–ด, ์ธ์Šคํƒ€๊ทธ๋žจ์— ๋กœ๊ทธ์ธํ•œ ์ œ๊ฐ€ ์–ด๋–ค ๊ฒŒ์‹œ๋ฌผ ๋งํฌ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ, ๋‹ค๋ฅธ ์˜ค๋ฆฌ์ง„(๋„๋ฉ”์ธ)์˜ ํ•ด์ปค๋Š” ์ œ ์ธ์ฆ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ† ํฐ์„ ํ™œ์šฉํ•ด ์ œ ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋นผ๋‚ด๊ฑฐ๋‚˜ ์ด์ƒํ•œ ๊ธ€์„ ์ œ ๊ณ„์ •์— ์˜ฌ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. ์ด๋Ÿฐ ์ผ์„ ์ผ์ฐจ์ ์œผ๋กœ ๋ง‰๊ธฐ ์œ„ํ•ด, ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ฐ™์€ ๋„๋ฉ”์ธ๊ณผ ํฌํŠธ, ํ”„๋กœํ† ์ฝœ ๋“ฑ์˜ ์š”์ฒญ์˜ ์‘๋‹ต๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

2. CORS๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์™œ ํ•„์š”ํ•œ์ง€ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

  1. ๊ฒฝ์šฐ์— ๋”ฐ๋ผ, ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ ์˜ค๋ฆฌ์ง„(์ถœ์ฒ˜)์—์„œ ์˜จ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋„ ์‘๋‹ต์„ ๋ณด๋‚ด์ฃผ๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ด๋•Œ, CORS, ์ฆ‰ cross origin resource sharing ์„ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ ๋„๋ฉ”์ธ(์„œ๋ธŒ๋„๋ฉ”์ธ) ์ด๋‚˜ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ/ํฌํŠธ๋กœ ์˜จ ์š”์ฒญ์„ SOP์—์„œ ์ œ์™ธ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. CORS ์ ‘๊ทผ์ œ์–ด ์‹œ๋‚˜๋ฆฌ์˜ค๋“ค๊ณผ ๊ทธ ๊ณผ์ •๋“ค์„ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”

  1. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „ ์‚ฌ์ „ ์š”์ฒญ์„ ๋ณด๋‚ด ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ preflight request-response ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
    1. ์ด ์‚ฌ์ „์š”์ฒญ์€ Options ๋ฉ”์†Œ๋“œ๋กœ ๋ณด๋‚ด์ง€๊ณ , ์ด์— ๋Œ€ํ•œ ์„œ๋ฒ„์˜ ์‚ฌ์ „ ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
    2. ์ด๋ฅผ ํ†ตํ•ด ๋ธŒ๋ผ์šฐ์ €๋Š” ํ•ด๋‹น ์š”์ฒญ์ด ํ—ˆ์šฉ๋œ ์š”์ฒญ์ž„์„ ํ™•์ธํ•˜๊ณ , ์‹ค์ œ ์š”์ฒญ์„ ์„œ๋ฒ„๋กœ ์˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค!
  2. ๊ทธ๋Ÿฐ๋ฐ ์ด ์‚ฌ์ „์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์š”์ฒญ์„ simple request๋ผ ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
    1. ์‹ฌํ”Œ ๋ฆฌํ€˜์ŠคํŠธ๋Š” ์š”์ฒญ ๋ฉ”์†Œ๋“œ๊ฐ€ GET, ์ผ๋ถ€ POST, HEAD ๋ฉ”์†Œ๋“œ ๋“ฑ์ด๊ณ  ์•ˆ์ „ํ•œ ํ—ค๋”๋งŒ ๋“ค์–ด๊ฐ€ ์žˆ์„ ์‹œ ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  3. ์‚ฌ์ „์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ, ์ž๊ฒฉ์ฆ๋ช…์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๊ฒ€์ฆ์ด ํ•„์š”ํ•  ๋•Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    1. ์ด๋•Œ๋Š” ์‚ฌ์ „์š”์ฒญ ํ—ค๋”์— credentials: include ๊ฐ€ ํฌํ•จ๋˜๊ณ 
    2. ์ด์— ๋Œ€ํ•œ ์‚ฌ์ „์‘๋‹ต์— ์ž๊ฒฉ์ฆ๋ช… ์š”์ฒญ์„ ํ—ˆ๊ฐ€ํ•œ๋‹ค๋Š” ํ—ค๋” ๊ฐ€ True๋กœ ํฌํ•จ๋˜์–ด ์žˆ์–ด์•ผ ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
profile
๐ŸŒฑ ํ•จ๊ป˜ ์ž๋ผ๋Š” ์ค‘์ž…๋‹ˆ๋‹ค ๐Ÿš€ rerub0831@gmail.com

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

comment-user-thumbnail
2022๋…„ 7์›” 31์ผ

์ •๋ฆฌ ์ตœ๊ณ ๋„ค์š”!!

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ