[10๋ถ„ ํ…Œ์ฝ”ํ†ก] ๐ŸŒณ ๋‚˜๋ด„์˜ CORS

๋ฐ•์ฒ ํ˜„ยท2023๋…„ 4์›” 10์ผ
0

์˜์ƒํ›„๊ธฐ

๋ชฉ๋ก ๋ณด๊ธฐ
85/161

movie

SOP(Same Origin Policy)

  • ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ๋ฐฉ์‹
  https: (ํ”„๋กœํ† ์ฝœ)
  //github.com(ํ˜ธ์ŠคํŠธ)
  :443(ํฌํŠธ)
  /cheorhyeon?tab=repositories#example
  • ์ถœ์ฒ˜(origin)๋ž€?
    • Protocol, Host, Port๋ฅผ ํ†ตํ•ด ๊ฐ™์€ ์ถœ์ฒ˜์ธ์ง€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋ชจ๋‘ ๊ฐ™์•„์•ผ ๋™์ผ ์ถœ์ฒ˜
    • ์ธํ„ฐ๋„ท ์ต์Šคํ”Œ๋กœ๋Ÿฌ : Port๊ฐ€ ๋‹ฌ๋ผ๋„ ๋™์ผ ์ถœ์ฒ˜๋กœ ์ธ์‹
  • localhost์™€ 127.0.0.1์„ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ๋‹ค๋ฅด๊ฒŒ ์ธ์‹
    • String Value๋กœ ๋น„๊ตํ•˜๊ธฐ์— ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ์ธ์‹

์™œ SOP๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ? ๋ณด์•ˆ์— ์œ„ํ•จ

์„ ๋Ÿ‰ํ•œ ์‚ฌ์šฉ์ž
1. ํŽ˜์ด์Šค๋ถ ์„œ๋น„์Šค ๋กœ๊ทธ์ธ ์ดํ›„ ์‚ฌ์šฉ(ํŽ˜์ด์Šค๋ถ์—์„œ ์ธ์ฆ ํ† ํฐ์„ ๋ฐ›์•„์˜ด)
2. ํ•ด์ปค : ํฅ๋ฏธ์ง„์ง„ํ•œ ๋‚ด์šฉ๊ณผ ๋งํฌ๋ฅผ ๋ฉ”์ผ์„ ํ†ตํ•ด ๋ณด๋ƒ„
3. ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๋‹ˆ hacker.ck ๋กœ ์ด๋™๋จ

  • ํ•ด๋‹น ๋งํฌ๋Š” ํŽ˜์ด์Šค๋ถ์— ๋‚˜๋Š” ๋ฐ”๋ณด๋‹ค ๋ผ๋Š” ํฌ์ŠคํŠธ ๊ฒŒ์‹œ ํ•˜๋ผ๋Š” ์ฝ”๋“œ ๋‚ดํฌ
  1. hacker.ck์—์„œ ์„ ๋Ÿ‰ํ•œ ์‚ฌ์šฉ์ž์˜ ํ† ํฐ์„ ์ด์šฉํ•ด ํŽ˜์ด์Šค๋ถ์— ๋‚˜๋Š” ๋ฐ”๋ณด๋‹ค ํฌ์ŠคํŠธ ๊ฒŒ์‹œ
  2. origin์ด ๋‹ค๋ฆ„
    • ํ•ด์ปค : hacker.ck != ํŽ˜์ด์Šค๋ถ : https://www.facebook.com/
    • ์ฆ‰ ๋‹ค๋ฅธ Origin -> Cross Origin ์ด๋ผ ํŒ๋‹จํ•˜๊ณ  ์š”์ฒญ์€ ๋ฐ›์•„๋“ค์—ฌ์ง€์ง€ ์•Š์Œ

๋งŒ์•ฝ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด?

  • CORS ํ•„์š”!

CORS(Cross-Origin Resource Sharing)

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

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

  • ๋‹จ์ˆœ ์š”์ฒญ(Simple Request)
  • ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ(Preflight Request)
  • ์ธ์ฆ์ •๋ณด ํฌํ•จ ์š”์ฒญ(Credentialed Request)

ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ(Preflight Request) : ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…

  • OPTIONS ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์˜ ๋ฆฌ์†Œ์Šค์— ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•œ ์ง€ ํ™•์ธํ•˜๋Š” ์ž‘์—…
    • (Preflight Request) ์š”์ฒญ์„ ์ด๋ ‡๊ฒŒ ๋ณด๋‚ผ๊ฑด๋ฐ ๊ฐ€๋Šฅํ•˜๋‹ˆ? ๋ผ๊ณ  ๋ฌผ์–ด๋ณด๋Š” ์š”์ฒญ
    • (Preflight Response) ์„œ๋ฒ„์ธก์—์„œ ๊ฐ€๋Šฅํ•œ์ง€์— ๋Œ€ํ•œ ์‘๋‹ต
    • ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์‹ค์ œ ์š”์ฒญ(Actual Request)๋ฅผ ๋ณด๋‚ธ๋‹ค.

Preflight Request ์š”์ฒญ ํฌ๋งท

  • Origin : ์š”์ฒญ ์ถœ์ฒ˜
  • Access-Control-Request-Method : ์‹ค์ œ ์š”์ฒญ ๋ฉ”์„œ๋“œ
  • Access-Control-Request-Headers : ์‹ค์ œ ์š”์ฒญ์˜ ์ถ”๊ฐ€ ํ—ค๋”

Preflight Response ์‘๋‹ต

  • Access-Control-Allow-Origin : ์„œ๋ฒ„์ธก ํ—ˆ๊ฐ€ ์ถœ์ฒ˜
  • Access-Control-Allow-Methods : ์„œ๋ฒ„ ์ธก ํ—ˆ๊ฐ€ ๋ฉ”์„œ๋“œ
  • Access-Control-Allow-Headers : ์„œ๋ฒ„ ์ธก ํ—ˆ๊ฐ€ ํ—ค๋”
  • Access-Control-Max-Age : preflight ์‘๋‹ต ์บ์‹œ ๊ธฐ๊ฐ„

Access-Control-Max-Age ์„ค์ • ํ•„์š” ์ด์œ 

  • Preflight ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•  ๊ฒฝ์šฐ ์‹ค์งˆ์ ์œผ๋กœ 2๋ฒˆ ์š”์ฒญ์ด ๋ณด๋‚ด์ง„๋‹ค.
    • Preflight๋กœ ์š”์ฒญ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ + ์‹ค์ œ ์š”์ฒญ
    • ๋งค๋ฒˆ 2๋ฒˆ ๋ณด๋‚ด์•ผํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ
    • ๋”ฐ๋ผ์„œ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์‘๋‹ต ์บ์‹ฑ ํ•ด๋‘๊ณ  ์š”์ฒญ์ด ์˜ค๋ฉด ์‚ฌ์ „ ํ™•์ธ ์—†์ด ๋ฐ”๋กœ ๋ณด๋‚ด๋Š”๊ฑฐ ๋ฐ›์•„๋“ค์ž„
      • PREFLIGHT RESPONSE ์†์„ฑ ์ค‘ Access-Control-Max-Age

Preflight Response๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ํŠน์ง•

  • ์‘๋‹ต ์ฝ”๋“œ๋Š” 200๋Œ€์—ฌ์•ผ ํ•œ๋‹ค.
  • ์‘๋‹ต ๋ฐ”๋””๋Š” ๋น„์–ด์žˆ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋‹จ์ˆœ ์š”์ฒญ(Simple Request)

  • preflight์™€ ๋‹ค๋ฅด๊ฒŒ ๋ฐ”๋กœ ๋ณธ ์š”์ฒญ์„ ๋‚ ๋ฆฌ๋ฉด์„œ ๊ทธ ์ฆ‰์‹œ Cross Origin์ธ์ง€ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ

์•„๋ž˜ ์กฐ๊ฑด ๋ชจ๋‘ ์ถฉ์กฑํ•ด์•ผ Simple Request

  • GET, POST, HEAD ๋ฉ”์„œ๋“œ ๋งŒ์กฑ
  • Content-Type ์•„๋ž˜ 3๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜
    • application/x-www-form-urlencoded
    • multipart/form-date
    • text/plain
  • ํ—ค๋”๋Š” Accept, Accept-Language, Content-Language, Content-Type๋งŒ ํ—ˆ์šฉ

Simple Request ํ๋ฆ„

์™œ Preflight๊ฐ€ ํ•„์š”ํ• ๊นŒ?

  • Simple Request ํ•œ๋ฐฉ์ด๋ฉด ๋๋‚˜๋Š”๊ฑด๋ฐ ์™œ ๊ตณ์ด 2๋ฒˆ(Preflight ์š”์ฒญ ๊นŒ์ง€) ๊ฐ€์•ผํ• ๊นŒ?
  • CORS๋ฅผ ๋ชจ๋ฅด๋Š” ์„œ๋ฒ„๋ฅผ ์œ„ํ•ด์„œ๋ผ๊ณ  ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ํŽธํ•จ

CORS ๋ชจ๋ฅด๋Š” ์„œ๋ฒ„

  • CORS ์•„๋ฌด๋Ÿฐ ์„ค์ • ์—†๋Š” ์„œ๋ฒ„
    • ์˜ˆ : simpleํ•œ get์š”์ฒญ
    • ์„œ๋ฒ„์—์„œ๋Š” CORS ์„ค์ •์„ ์•„๋ฌด๊ฒƒ๋„ ์•ˆํ•จ
    • ๊ทธ๋Œ€๋กœ ์‘๋‹ต ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ ALLOW-ORIGIN์ด ์—†๊ธฐ์— ๋ธŒ๋ผ์šฐ์ €์—์„œ CORS ์—๋Ÿฌ!๋ผ ์‘๋‹ต

Preflight๊ฐ€ ์—†๋‹ค๋ฉด?

  • ๋งŒ์ผ delete ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ†ต์‹ ํ•˜๋Š”๋ฐ Preflight ์š”์ฒญ์ด ์—†๋‹ค๋ฉด
    • ์‹ค์ œ ์„œ๋ฒ„์—์„œ๋Š” Data ์‚ญ์ œ ๋ฐ ์„ฑ๊ณต ์‘๋‹ต
    • SOP ์œ„๋ฐ˜์ด๋ผ CORS ์—๋Ÿฌ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋‚ด๋Š”๋ฐ ์ด๋ฏธ ์„œ๋ฒ„์—์„œ๋Š” ์‚ญ์ œ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ์ƒํ™ฉ
  • ์ฆ‰ CORS ์—๋Ÿฌ๋ฅผ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ญ์ œ๋œ ๋‹ค์Œ์— ์‘๋‹ต๋ฐ›๊ธฐ์— ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ์ผ์ˆ˜๋„ ์žˆ์Œ

Preflight ์š”์ฒญ ํ๋ฆ„

  • Preflight๋Š” ์‚ฌ์ „ ์š”์ฒญ์œผ๋กœ ์„œ๋ฒ„์—์„œ ์–ด๋–ค ๋™์ž‘์„ ํ•˜์ง€ ์•Š์Œ
  • Preflight ์š”์ฒญ์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š์Œ
    • ์„œ๋ฒ„๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ์ž˜ ์ง€์ผœ์ง

์ธ์ฆ์ •๋ณด ํฌํ•จ ์š”์ฒญ(Credentialed Request)

  • ์ธ์ฆ ๊ด€๋ จ ํ—ค๋” ํฌํ•จํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์š”์ฒญ
    • JWT๋ฅผ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ž๋™์œผ๋กœ ๋‹ด์•„์„œ ๋ณด๋‚ด๊ณ  ์‹ถ์„๋•Œ credentials๋ฅผ include
  • ํด๋ผ์ด์–ธํŠธ์ธก credentials : include
  • ์„œ๋ฒ„์ธก Access-Control-Allow-Credentials : true
    • Access-Control-Allow-Origin: *๋Š” ์•ˆ๋จ, ํŠน์ • url ๋ช…์‹œ ํ•„์š”
      • Credentials true์ธ๋ฐ Origin *๋ฉด ์˜ˆ์™ธ ํ„ฐ์ง

CORS ํ•ด๊ฒฐ

ํ”„๋ก ํŠธ ํ”„๋ก์‹œ ์„œ๋ฒ„ ์„ค์ •(๊ฐœ๋ฐœ ํ™˜๊ฒฝ)

  • ๋ธŒ๋ผ์šฐ์ €์—์„œ 8181 -> ํ”„๋ก ํŠธ 8081 ๋ฐ›์•„์„œ ์„œ๋ฒ„ 8080์œผ๋กœ ํ† ์Šค
  • ๋‚ด๋ถ€์ ์œผ๋กœ 8080 ํฌํŠธ๋กœ ๋ฐ”๊ฟ”์„œ ์š”์ฒญ ์ฒ˜๋ฆฌ
  • ์‘๋‹ตํ• ๋•Œ 8081๋กœ ์‘๋‹ต

์ง์ ‘ ํ—ค๋”์— ์„ค์ •

  • ์˜์ƒ์—์„œ ๋„˜์–ด๊ฐ
  • ๋‹ค์†Œ ๋ฒˆ๊ฑฐ๋กœ์›€

์Šคํ”„๋ง ๋ถ€ํŠธ ์ด์šฉ ํ•ด๊ฒฐ

์‹ค์Šต

Preflight ์—†๋Š” ๊ฒฝ์šฐ ์˜ˆ์‹œ(Simple Request Get)
  • 8081 ํฌํŠธ์—์„œ 8080 ์„œ๋ฒ„๋กœ api ์š”์ฒญ
    • ์‹ค์ œ๋กœ Server์—์„œ OK๋กœ ์‘๋‹ต
    • ํ•˜์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ CORS ๋ฌธ์ œ ๋ฐœ์ƒ
    • ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ๋Œ€๋กœ preflight ์—†์—ˆ๋”๋ผ๋ฉด..!
Spring @CrossOrigin ์–ด๋…ธํ…Œ์ด์…˜
  • ์ปจํŠธ๋กค๋Ÿฌ์— ์„ค์ •ํ•˜๋ฉด ๋๋‚จ
  • ๊ฐœ๋ณ„ ๋ฉ”์„œ๋“œ๋„ ๊ฐ€๋Šฅ
// origins ์„ค์ • ์•ˆํ•˜๋ฉด default ์ „์ฒด์ผ๋“ฏ
@CrossOrigin(origins = "http://localhost:8081")

// ์˜ค๋ฅ˜!
@CrossOrigin(origins = "*", allowCredentials = "true)
  • ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ๋Œ€๋กœ ์•„๋ž˜ ์„ค์ •์„ ๋‘๊ฐœ ๊ฐ™์ด ๋™์‹œ ์‚ฌ์šฉํ•˜๋ฉด ์˜ค๋ฅ˜๋‚จ ํ™•์ธ
    • origins = *
    • allowCredentials = "true"
WebMvcConfigurer ๊ตฌํ˜„์ฒด
  • @CrossOrigin ์–ด๋…ธํ…Œ์ด์…˜์˜ ๊ฒฝ์šฐ ํ•„์š”ํ•œ๊ณณ์— ๋ชจ๋‘ ๋ถ™์—ฌ์•ผ ํ•œ๋‹ค.
  • ์ „์—ญ์ ์œผ๋กœ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด CorsConfiguration ์ƒ์„ฑ
@Configuration
public class CorsConfiguration implements WebMvcConfigurer  {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
    .allowedOrigins("http://localhost:8081");
  }
}
profile
๋น„์Šทํ•œ ์–ด๋ ค์›€์„ ๊ฒช๋Š” ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋„์›€์ด ๋˜๊ธธ

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