TIL

์š”์ฒญ์— ์ฟ ํ‚ค๊ฐ€ ์•ˆ ๋‹ด๊ฒจ์š”.. SameSite=None? Strict?

inz1234 2025. 3. 2. 20:47

๐Ÿšจ  TroubleShotting

๋ฌธ์ œ ๋ฐœ์ƒ์˜ ๋ฐฐ๊ฒฝ - As Is

ํ˜„์žฌ ์›น์†Œ์ผ“์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์‹ค์‹œ๊ฐ„ ํˆฌํ‘œ ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœ ์ค‘์ด๋‹ค.
์„œ๋น„์Šค์˜ ๊ฐ„๋‹จํ•จ์„ ๊ณ ๋ คํ•˜์—ฌ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ด ๊ตณ์ด ํ•„์š”์—†๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์ง€๋งŒ, ํˆฌํ‘œ์˜ ์ฃผ์ฒด์ธ ์œ ์ € ์‹๋ณ„ ๊ธฐ๋Šฅ์€ ํ•„์š”ํ–ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์„ธ์…˜์„ ์ด์šฉํ•ด์„œ  ์„œ๋ฒ„์—์„œ ์„ธ์…˜ ID๋ฅผ ๋ฐœ๊ธ‰ ๋ฐ ์ฟ ํ‚ค์— ๋‹ด์•„์ฃผ๋ฉด - ํ”„๋ก ํŠธ์—์„œ ์š”์ฒญ๋งˆ๋‹ค ์ฟ ํ‚ค๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์œ ์ €๋ฅผ ์‹๋ณ„ํ•˜๊ณ ์ž ํ–ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๋ถ„๋ช…ํžˆ ์„œ๋ฒ„์—์„œ sessionID๋ฅผ ๋ฐœ๊ธ‰ํ•ด์„œ ์ฟ ํ‚ค์— ๋„ฃ์–ด์ฃผ์—ˆ๊ณ , ํ”„๋ก ํŠธ์—์„œ๋„ document.cookies๋กœ ์ฟ ํ‚ค ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‚˜,

์š”์ฒญ์—๋Š” ์ฟ ํ‚ค๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š๋Š” ํ˜„์ƒ

How(๊ณผ์ •) ?

์‹œํ–‰์ฐฉ์˜ค 1

  • Websocket ์š”์ฒญ ํ—ค๋”์— ํˆฌํ‘œ ์ •๋ณด๋ฅผ ๋‹ด์•„์„œ ๋ฐฑ์—”๋“œ๋กœ ๋ณด๋‚ด๋ ค๊ณ  ํ–ˆ๋‹ค.
    • ์‹คํŒจ
      • ์›น์†Œ์ผ“ ์š”์ฒญ์€ ์ฒ˜์Œ์—๋Š” http๋กœ ์‹œ์ž‘ํ•˜์—ฌ ํ•ธ๋“œ์‰์ดํฌ -> Websocket ํ”„๋กœํ† ์ฝœ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œ ๋˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค.
      • ์ด ๋•Œ, Websocket ํ”„๋กœํ† ์ฝœ์—๋Š” Header ์ธํ„ฐํŽ˜์ด์Šค ์ž์ฒด๊ฐ€ ์—†๋‹ค.
      • ์ฆ‰, Websocket ํ”„๋กœํ† ์ฝœ ์ž์ฒด๋Š” ํ—ค๋”๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์—†๋‹ค.

์‹œํ–‰์ฐฉ์˜ค 2

  • ๊ทธ๋Ÿผ ํ•ธ๋“œ์‰์ดํฌ ๋‹จ๊ณ„๊นŒ์ง€๋งŒ์ด๋ผ๋„ ์ฟ ํ‚ค๋ฅผ ๋‹ด์•„์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด์ž.
  • ํ”„๋ก ํŠธ์—์„œ ์šฐ์„  `credentials: include`(fetch) ๋˜๋Š”`withCredentials: true`(Axios)๋ฅผ ์„ค์ •ํ•ด์•ผ ์ฟ ํ‚ค๊ฐ€ ์š”์ฒญ์— ํฌํ•จ๋˜๋ฏ€๋กœ ์ถ”๊ฐ€
    • ์‹คํŒจ
    • ์š”์ฒญ์— ์ฟ ํ‚ค๋ฅผ ๋‹ด์•„์„œ ๋ณด๋‚ผ ๋•Œ๋Š” ๋ช‡ ๊ฐ€์ง€ ์กฐ๊ฑด์ด ํ•„์š”ํ•จ
      • CORS - ๊ฐ™์€ ์ถœ์ฒ˜์ธ๊ฐ€?
        • No, ํ˜„์žฌ ํ”„๋ก ํŠธ๋Š” ๊ฐœ๋ฐœ ๋ชจ๋“œ๋กœ `localhost:3300`, ๋ฐฑ์—”๋“œ๋Š” `golaping.site` ์ฃผ์†Œ ์‚ฌ์šฉ ์ค‘
        • ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ, Access-origin ์„ค์ • ์™ธ์—๋„ `Samesite=None` ์„ค์ • ํ•„์š”
        • `Samesite=None`์ด๋ฉด, `secure=true` ์„ค์ • ๋ฐ https ํ™˜๊ฒฝ ํ•„์š”
        • SSL ์ธ์ฆ์„œ ์„ค์น˜
  • ์ด ๊ณผ์ •์„ ๊ฑฐ์ณ์„œ `localhost:3300` ์—์„œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์ฟ ํ‚ค๋ฅผ ๋‹ด์•„ ์š”์ฒญ ๋ณด๋‚ด๊ธฐ์— ์„ฑ๊ณตํ–ˆ๋‹ค.

์‹œํ–‰์ฐฉ์˜ค 3

๊ทธ๋Ÿฐ๋ฐ, ๋ฌธ๋“ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

`Samesite=None`์ด ํ—ˆ์šฉ๋˜๋ฉด, CSRF ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ?

CSRF ๊ณต๊ฒฉ ์œ„ํ—˜์„ฑ์„ ๋ง‰๋Š” ๋ฐฉ๋ฒ•์€ ๋ณดํ†ต ์•„๋ž˜ 3๊ฐ€์ง€์ด๋‹ค.

  • CSRF ํ† ํฐ ์‚ฌ์šฉ
  • CORS ์„ค์ • - ํ—ˆ์šฉ๋œ ๋„๋ฉ”์ธ์—์„œ๋งŒ ์š”์ฒญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œ
  • `SameSite=Strict` - ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์—์„œ ์ฟ ํ‚ค๊ฐ€ ์ „์†ก๋˜์ง€ ์•Š๋„๋ก  

SameSite = Strict

๊ทธ ์ค‘ `SameSite=Strict`๋ฅผ ์ ์šฉํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด์•˜๋‹ค.
๋จผ์ €, SameSite=Strict ๋ž€, ๋™์ผ ์‚ฌ์ดํŠธ ๊ฐ„์˜ ์š”์ฒญ์—๋งŒ ์ฟ ํ‚ค๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ •์ฑ…์ด๋‹ค.
๊ทธ๋Ÿผ ์—ฌ๊ธฐ์„œ ๋™์ผ ์‚ฌ์ดํŠธ๋ž€? ์•„๋ž˜ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด

  • "์Šคํ‚ค๋งˆ์™€ eTLD+1(TLD + TLD ๋ฐ”๋กœ ์•ž์˜ ๋„๋ฉ”์ธ)์ด ๋™์ผํ•œ ์›น์‚ฌ์ดํŠธ" ๊ฐ€ ๋™์ผ ์‚ฌ์ดํŠธ์ด๋‹ค.

ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ ๊ฐ„์˜ ๋„๋ฉ”์ธ์„ ์ผ์น˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ญ๊ฐ€ ์žˆ์„๊นŒ ์ƒ๊ฐํ•ด๋ณด์•˜๊ณ , 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ๋– ์˜ฌ๋ž๋‹ค.

๋ฐฉ๋ฒ• 1

  • ํ”„๋ก ํŠธ EC2 ์„œ๋ฒ„์˜ nginX์—์„œ proxy_pass๋ฅผ ํ†ตํ•ด Host  ํ—ค๋”๋ฅผ ๋ฐฑ์—”๋“œ ํ˜ธ์ŠคํŠธ๋กœ ๋ณ€๊ฒฝ 
    ์ฆ‰, ๋ฐฑ์—”๋“œ์—์„œ๋Š” ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ๊ฐ™์€ ์‚ฌ์ดํŠธ๋กœ ์ธ์‹ํ•˜๋„๋ก ํ•˜๊ธฐ
server {
    listen 80;
    server_name frontend.com;  # ํ”„๋ก ํŠธ์—”๋“œ ๋„๋ฉ”์ธ

    location /api/ {
        proxy_pass http://api.com/;  # ๋ฐฑ์—”๋“œ API ์„œ๋ฒ„๋กœ ํ”„๋ก์‹œ
        proxy_set_header Host api.com;  # ---> 'Host' ํ—ค๋”๋ฅผ api.com์œผ๋กœ ์„ค์ •
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
  • Host ํ—ค๋”๋ž€?
    • HTTP ์š”์ฒญ์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋Œ€์ƒ์˜ ๋„๋ฉ”์ธ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, http://api.com/somepath๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ, Host ํ—ค๋”๋Š” api.com์ด ๋œ๋‹ค.

  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด,  ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋Š” frontend.com ์œผ๋กœ ์‹œ์ž‘ํ•œ ์š”์ฒญ์ด api.com์—์„œ ์˜จ ๊ฒƒ์ฒ˜๋Ÿผ ์ฒ˜๋ฆฌํ•˜์—ฌ `SameSite=Strict`๋กœ ์„ค์ •์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

๋ฐฉ๋ฒ• 2

ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ๋ชจ๋‘ ์ตœ์ƒ์œ„ ๋„๋ฉ”์ธ์„ ๊ณต์œ , ์„œ๋ธŒ๋„๋ฉ”์ธ์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ

Type: A
Name: frontend
Value: XX.XX.XX.XX  # EC2 ํผ๋ธ”๋ฆญ IP
TTL: 3600

Type: A
Name: api
Value: YY.YY.YY.YY  # ๋ฐฑ์—”๋“œ EC2 ํผ๋ธ”๋ฆญ IP
TTL: 3600
  • AWS Route53 ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐฑ์—”๋“œ ๋„๋ฉ”์ธ์„ ์„œ๋ธŒ๋„๋ฉ”์ธ์œผ๋กœ ์„ค์ • ๊ฐ€๋Šฅํ•˜๋‹ค.

what(๊ฒฐ๊ณผ) - To Be

์šฐ๋ฆฌ๋Š” ๊ฒฐ๊ตญ ์„œ๋ธŒ๋„๋ฉ”์ธ์„ ์„ค์ •ํ•˜๋Š”, ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ–ˆ๋‹ค.

๊ทผ๋ฐ ์ด ๋ฐฉ๋ฒ•.. AWS์˜ Route53์„ ์‚ฌ์šฉํ–ˆ๋”๋‹ˆ ๊ณผ๊ธˆ์ด ๋˜๋„ค... ๋ฉ”์ผ์ด ๋‚ ๋ผ์˜ด


๊ณง nginX ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณ€๊ฒฝํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค. 
๋ณ€๊ฒฝํ•˜๊ฒŒ ๋˜๋ฉด ๋‹ค์‹œ ๊ธฐ๋กํ•˜์ž.


๐Ÿ’ก ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ์ 

  • ๋™์ผ ์ถœ์ฒ˜์™€ ๋™์ผ ์‚ฌ์ดํŠธ ๊ฐ„์˜ ์ฐจ์ด์— ๋Œ€ํ•ด์„œ ์ œ๋Œ€๋กœ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.
    • ๋™์ผ ์ถœ์ฒ˜: ์Šคํ‚ด + ๋„๋ฉ”์ธ + ํฌํŠธ๊นŒ์ง€ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.
    • ๋™์ผ ์‚ฌ์ดํŠธ: ์Šคํ‚ด + eTLD+1 ๊นŒ์ง€๋งŒ ์ผ์น˜ํ•˜๋ฉด ๋œ๋‹ค(ํฌํŠธ ๋‹ฌ๋ผ๋„ ๋จ)

์ถœ์ฒ˜