HTTP๋ ๋น์ฐ๊ฒฐ์ฑ, ๋ฌด์ํ์ฑ์ด ๊ธฐ๋ณธ์ด๋ผ๊ณ ํ๋๋ฐ..
์ ์ผํ๋ชฐ์ ๋ก๊ทธ์ธ ํ ์ํ๋ก ๋ค๋ฅธ ํ์ด์ง๋ฅผ ๋์๋ค๋
๋ ์ฅ๋ฐ๊ตฌ๋๊ฐ ์ ์ง ๋๋ ๊ฑธ๊น?
๊ทธ๊ฒ์ ๋ฐ๋ก ์ฟ ํค ๋๋ถ!
์ฟ ํค๋ ์๋ฒ์์ ํด๋ผ์ด์ธํธ์ ์์์ฑ์๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์๋ฒ๋ ํด๋ผ์ด์ธํธ์ ์ฟ ํค๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์ฆ, ๋จ์ํ ์๋ฒ์์ ํด๋ผ์ด์ธํธ์๊ฒ ์ฟ ํค๋ฅผ ์ ์กํ๋ ๊ฒ๋ง์ ์๋ฏธํ์ง๋ ์๊ณ
ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก ์ฟ ํค๋ฅผ ๋ค์ ์ ์กํ๋ ๊ฒ๋ ํฌํจ๋๋ค๋ ๊ฒ.
์ฃผ๋ก ์ฌ์ฉ์ ์ ํธ, ํ ๋ง ๋ฑ ์ฅ์๊ฐ ๋ณด์กดํด์ผ ํ๋ ์ ์ฅ์ ์ ํฉํ๋ค.
์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ํน์ ํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์๋ค.
์๋ฒ๋ ์ฟ ํค๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๋ถ๋ฌ์ ์ฌ์ฉํ ์ ์์ง๋ง,
์๋ฌด ๋๋ ๊ฐ์ ธ์ฌ ์๋ ์๋ค. ํน์ ์กฐ๊ฑด๋ค์ด ๋ง์กฑ๋์ด์ผ ๋ค์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
// http ํค๋๋ฅผ ์ฌ์ฉํด ์ฟ ํค ์ต์
์ผ๋ก ํํํ ์ ์๋ค.
'Set-Cookie':[
'cookie=yummy',
'Secure=Secure; Secure',
'HttpOnly=HttpOnly; HttpOnly',
'Path=Path; Path=/cookie',
'Doamin=Domain; Domain=codestates.com'
]
ย Domainย
www.google.com
๊ณผ ๊ฐ์ ์๋ฒ์ ์ ์ํ ์ ์๋ ์ด๋ฆ์ด๋ค.
ํฌํธ ๋ฐ ์๋ธ ๋๋ฉ์ธ ์ ๋ณด์ ์ธ๋ถ ๊ฒฝ๋ก๋ ํฌํจํ์ง ์๋๋ค.
// ๋๋ฉ์ธ ์์
Q. http://www.localhost.com:3000/users/login์ ๋๋ฉ์ธ์?
A. localhost.com
๋ง์ฝ ์ฟ ํค ์ต์
์์ ๋๋ฉ์ธ ์ ๋ณด๊ฐ ์กด์ฌํ๋ค๋ฉด ํด๋ผ์ด์ธํธ์์๋
์ฟ ํค์ ๋๋ฉ์ธ ์ต์
๊ณผ ์๋ฒ์ ๋๋ฉ์ธ์ด ์ผ์นํด์ผ๋ง ์ฟ ํค๋ฅผ ์ ์กํ ์ ์๋ค.
(naver.com์์ ๋ฐ์ ์ฟ ํค๋ฅผ google.com์ ์ ์กํ๋ ์ผ์ ๋ง์ ์ ์์)
ย Pathย
์ธ๋ถ ๊ฒฝ๋ก๋ก์จ ์๋ฒ๊ฐ ๋ผ์ฐํ
ํ ๋ ์ฌ์ฉํ๋ ๊ฒฝ๋ก๋ฅผ ์๋ฏธํ๋ค.
์์ฑํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก /
์ด ์ค์ ๋๋ค.
// Path ์์
Q. http://www.localhost.com:3000/users/login์ Path๋?
A. /users/login
-----
// Path๋ ์ค์ ๋ ๊ฒฝ๋ก๋ฅผ ํฌํจํ๋ ํ์ ๊ฒฝ๋ก๋ก ์์ฒญ์ ํ๋๋ผ๋ ์ฟ ํค๋ฅผ ์๋ฒ์ ์ ์กํ ์ ์๋ค.
// Path๊ฐ /users๋ก ์ค์ ๋์ด ์๊ณ , ์์ฒญํ๋ ์ธ๋ถ ๊ฒฝ๋ก๊ฐ /users/tata ์ธ ๊ฒฝ์ฐ๋ผ๋ฉด ์ฟ ํค ์ ์ก์ด ๊ฐ๋ฅ.
// But, /posts/tata๋ก ์ ์ก๋๋ ์์ฒญ์ Path ์ต์
(/users)์ ๋ง์กฑํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์๋ฒ๋ก ์ฟ ํค๋ฅผ ์ ์กํ ์ ์๋ค.
ย MaxAge or Expiresย
์ฟ ํค์ ์ ํจ ๊ธฐ๊ฐ์ ์ ํ๋ ์ต์ ์ด๋ค. (๋ณด์ ์ธก๋ฉด์์ ์ค์ํจ)
MaxAge : ์ฟ ํค๊ฐ ์ ํจํ ์๊ฐ์ ์ด ๋จ์๋ก ์ค์ ํ๋ ์ต์
Expires : ํด๋ผ์ด์ธํธ์ ์๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ ํจํ ๋ ์ง์ ์ง์ ๊ฐ๋ฅ
์ดํ ์ง์ ๋ ์๊ฐ, ๋ ์ง๋ฅผ ์ด๊ณผํ๊ฒ ๋๋ฉด ์ฟ ํค๋ ์๋์ผ๋ก ํ๊ดด๋๋ค.
์ฟ ํค๋ ์ ์ต์
์ ์ฌ๋ถ์ ๋ฐ๋ผ ์ธ์
์ฟ ํค์ ์์์ฑ ์ฟ ํค๋ก ๋๋ ์ง๋ค.
๐ช ์ธ์
์ฟ ํค - Session Cookie
MaxAge
๋๋ Expires
์ต์
์ด ์๋ ์ฟ ํค๋ก,
๋ธ๋ผ์ฐ์ ๊ฐ ์คํ ์ค์ผ ๋ ์ฌ์ฉํ ์ ์๋ ์์ ์ฟ ํค์ด๋ค.
(๋ธ๋ผ์ฐ์ ์ข
๋ฃ โ ์ฟ ํค ์ญ์ )
๐ช ์์์ฑ ์ฟ ํค - Persistent Cookie
๋ธ๋ผ์ฐ์ ์ ์ข
๋ฃ ์ฌ๋ถ์ ์๊ด์์ด
MaxAge
๋๋ Expires
์ ์ง์ ๋ ์ ํจ์๊ฐ๋งํผ ์ฌ์ฉ๊ฐ๋ฅํ ์ฟ ํค
ย Secureย
์ฌ์ฉํ๋ http, https ํ๋กํ ์ฝ์ ๋ฐ๋ฅธ ์ฟ ํค์ ์ ์ก ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ์ต์ ์ด๋ค.
์ต์
์ด true : HTTPS๋ฅผ ์ด์ฉํ๋ ๊ฒฝ์ฐ์๋ง ์ฟ ํค ์ ์ก ๊ฐ๋ฅ.
์ต์
์ด ์์ ๋ : ํ๋กํ ์ฝ์ ์๊ด์์ด ์ฟ ํค ์ ์ก ๊ฐ๋ฅ.
// ์์
Secure ์ต์
์ด ์๋ค๋ฉด ํ๋กํ ์ฝ์ ์๊ด์์ด
http://www.tata-velog.com ๋๋
https://www.tata-velog.com์ ๋ชจ๋ ์ฟ ํค๋ฅผ ์ ์กํ ์ ์๋ค.
โ๏ธ์ฐธ๊ณ ) ๋๋ฉ์ธ์ด localhost์ธ ๊ฒฝ์ฐ์๋ HTTPS๊ฐ ์๋์ฌ๋ ์ฟ ํค ์ ์ก์ด ๊ฐ๋ฅํ๋ค.
ย HttpOnlyย
์๋ฐ์คํฌ๋ฆฝํธ๋ก ์ฟ ํค์ ์ ๊ทผ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค.
์ต์
์ด true โ document.cookie
๋ฅผ ์
๋ ฅ ์ ์ฟ ํค์ ์ ๊ทผ์ด ๋ถ๊ฐ
์ต์
์ด false(๊ธฐ๋ณธ๊ฐ) โ document.cookie
๋ฅผ ์ด์ฉํด ์ฟ ํค์ ์ ๊ทผ ๊ฐ๋ฅํ๋ฏ๋ก, ์ฟ ํค๊ฐ ํ์ทจ๋ ์ํ์ด ์๋ค.
ย SameSiteย
Cross-Origin ์์ฒญ์ ๋ฐ์ ๊ฒฝ์ฐ, ์์ฒญ์์ ์ฌ์ฉํ
๋ฉ์๋์ ํด๋น ์ต์
์ ์กฐํฉ์ ๊ธฐ์ค์ผ๋ก ์๋ฒ์ ์ฟ ํค ์ ์ก ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋๋ค.
์ฌ์ฉ ๊ฐ๋ฅํ ์ต์
Lax
: GET ๋ฉ์๋์ ๋ํด์๋ง ์ฟ ํค๋ฅผ ์ ์ก.
Strict
: ๊ฐ์ฅ ์๊ฒฉํ ์ต์
์ผ๋ก, same-site์ธ ๊ฒฝ์ฐ์๋ง ์ฟ ํค๋ฅผ ์ ์ก.
None
: ํญ์ ์ฟ ํค๋ฅผ ์ ์ก. ์ฟ ํค ์ต์
์ค Secure ์ต์
์ด ํ์ํ๋ค.
โ๏ธ์ฐธ๊ณ ) same-site๋ ์์ฒญ์ ๋ณด๋ธ Origin๊ณผ ์๋ฒ์ ๋๋ฉ์ธ, ํ๋กํ ์ฝ, ํฌํธ๊ฐ ๊ฐ์ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ค. ์ด ์ค ํ๋๋ผ๋ ๋ค๋ฅด๋ค๋ฉด Cross-Origin์ผ๋ก ๊ตฌ๋ถ๋๋ค.
์๋ฒ์์ ์ด๋ฌํ ์ต์
๋ค์ ์ง์ ํ ๋ค์, ํด๋ผ์ด์ธํธ๋ก ์ฟ ํค๋ฅผ ์ฒ์ ์ ์กํ๊ฒ
๋๋ค๋ฉด ํค๋์ Set-Cookie๋ผ๋ ํ๋กํผํฐ๋ก ์ฟ ํค๋ฅผ ๋ด์ ์ ์กํ๋ค.
์ดํ ํด๋ผ์ด์ธํธ์์ ์๋ฒ์๊ฒ ์ฟ ํค๋ฅผ ์ ์กํด์ผ ํ๋ค๋ฉด ํด๋ผ์ด์ธํธ๋
ํค๋์ Cookie๋ผ๋ ํ๋กํผํฐ์ ์ฟ ํค๋ฅผ ๋ด์ ์๋ฒ์ ์ฟ ํค๋ฅผ ์ ์กํ๊ฒ ๋๋ค.
(๐คซHttpOnly ์ต์
์ ์ฌ์ฉํ์ง ์์๋ค๋ฉด
์ฟ ํค์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋ด๋ ๊ฒ์ ์ํํ๋ ๊ผญ ์ค์ ํ๊ธฐ)
โ๋ฆฌ๋ค์ด๋ ํธ๋ ์ด๋ป๊ฒ ํ๋ ๊ฑด๊ฐ์?
redirect ๋ฉ์๋์ ์๋ํฌ์ธํธ๋ฅผ ์ ๋ฌํด์ฃผ๋ฉด ๋๋ค.
res.redirect("/userinfo")
์ฟ ํค ์ค์ ์์
// ๋ก๊ทธ์์ ์์
module.exports = (req, res) => {
const cookiesOption = {
domain: "localhost",
path: "/",
httpOnly: true,
sameSite: "none",
secure: true,
};
// clearCookie('์ฟ ํค์ ํค', cookieOption) ๋ฉ์๋๋ก ํด๋น ํค๋ฅผ ๊ฐ์ง ์ฟ ํค๋ฅผ ์ญ์ ํ ์ ์๋ค.
res.status(205).clearCookie("cookieId", cookiesOption).send("logout");
};
-----------
// ์ฟ ํค ์ฐ๊ธฐ ์์
res.cookie("cookieId", userInfo.id, cookiesOption).send("logout")
์๋ฒ๊ฐ Client์ ์ ์ผํ๊ณ ์ํธํ๋ ID๋ฅผ ๋ถ์ฌํ๋ค. (์ค์ ๋ฐ์ดํฐ๋ ์๋ฒ์์ ๊ด๋ฆฌ)
์๋ฒ๊ฐ "ํด๋น ์ ์ ๋ ์ธ์ฆ์ ์ฑ๊ณตํ์"์ ์๊ณ ์๋ค๋ฉด,
์ ์ ๊ฐ ๋งค๋ฒ ๋ก๊ทธ์ธํ ํ์๊ฐ ์์ ๊ฒ์ด๋ค.
์๋ฒ: ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์ฑ๊ณตํ์์ ์๊ณ ์์ด์ผ ํจ.
ํด๋ผ์ด์ธํธ: ์ธ์ฆ ์ฑ๊ณต์ ์ฆ๋ช
ํ ์๋จ์ ๊ฐ๊ณ ์์ด์ผ ํจ.
๐ ย ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์ฑ๊ณตํ ์ํ๋ฅผ ์ธ์
ย ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๏ผ ์๋ฒ๋ ์ผ์ข
์ ์ ์ฅ์(redis์ ๊ฐ์ DB)์ ์ธ์
์ ์ ์ฅํ๋ค.
๏ผ ์ธ์
์ด ๋ง๋ค์ด์ง๋ฉด, ๊ฐ ์ธ์
์ ๊ตฌ๋ถํ ์ ์๋ ์ธ์
์์ด๋๋ ๋ง๋ค์ด์ง๋๋ฐ,
ย ย ย ย ๋ณดํต ํด๋ผ์ด์ธํธ์ ์ธ์
์ฑ๊ณต์ ์ฆ๋ช
ํ ์๋จ์ผ๋ก์จ ์ธ์
์์ด๋๋ฅผ ์ ๋ฌํ๋ค.
๏ผ ์ด๋ ์น์ฌ์ดํธ์์ ๋ก๊ทธ์ธ์ ์ ์งํ๊ธฐ ์ํ ์๋จ์ผ๋ก ์ฟ ํค๋ฅผ ์ฌ์ฉํ๋ค.
ย ย ย ย (์๋ฒ์์ ๋ฐ๊ธ ๋ฐ์ ์ธ์
์์ด๋๋ฅผ ์ฟ ํค์ ์ ์ฅ)
๏ผ ์ธ์
์คํ ์ด์ ํด๋น ์ธ์
์ด ์กด์ฌํ๋ค๋ฉด ์๋ฒ๋ ํด๋น ์์ฒญ์ ์ ๊ทผ ๊ฐ๋ฅํ๋ค๊ณ ํ๋จํ๋ค.
์ธ์
์์ด๋๊ฐ ๋ด๊ธด ์ฟ ํค๋ ํด๋ผ์ด์ธํธ์ ์ ์ฅ๋์ด ์์ผ๋ฉฐ,
์๋ฒ๋ ์ธ์
์ ์ ์ฅํ๊ณ ์๋ค.(์๋ฒ๋ ๊ทธ์ ์ธ์
์์ด๋๋ก๋ง ์ธ์ฆ ์ฌ๋ถ๋ฅผ ํ๋จ)
์๋ฒ: ์ธ์
์ ๋ณด๋ฅผ ์ญ์ ํด์ผ ํจ.
ํด๋ผ์ด์ธํธ: ์ฟ ํค๋ฅผ ๊ฐฑ์ ํ๊ฑฐ๋ ์ญ์ ํด์ผ ํจ.
ํด๋ผ์ด์ธํธ์์ ์ธ์
์ ๋ณด๋ฅผ ์์ ๊ธฐ ์ํด์๋
res.cookie
๋ก ์ฟ ํค์ ๊ฐ์ ๋ฌดํจํ ๊ฐ์ผ๋ก ๊ฐฑ์ ํ๊ฑฐ๋,
res.clearCookie
๋ก ์ฟ ํค๋ฅผ ์ญ์ ํด๋ฒ๋ฆฌ๋ฉด ๋๋ค.
Node.js์๋ ์ด๋ฐ ์ธ์
์ ๋์ ๊ด๋ฆฌํด ์ฃผ๋
express-session
์ด๋ผ๋ ๋ชจ๋์ด ์กด์ฌํ๋ค.
secret ์ต์
์ ๋น๋ฐํค๋ฅผ ์ด์ฉํด ์ํธํํ์ฌ
์ธ์
id๋ผ๋ ๊ฒ์ ์์ฑํ๊ณ , ์ด๊ฒ์ ํด๋ผ์ด์ธํธ์๊ฒ ์ฟ ํค๋ก ์ ์กํ๋ค.
(์ด๋์ ์น์
๊ฐ์ฒด๋ ์ ์ ๋ณ๋ก ๋
๋ฆฝ์ ์ผ๋ก ์์ฑ๋ ๊ฐ์ฒด์)
const express = require('express');
const session = require('express-session');
const app = express();
// ํด๋ผ์ด์ธํธ์ ์ ์ ์ ๊ฐ์ธ์ ๋ณด๋ฅผ ๋ด์ง ์๊ณ ๋
// ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์ธ์
id๋ฅผ ์ด์ฉํด ์ ์ ์ ์ธ์ฆ์ฌ๋ถ๋ฅผ ํ๋จํ ์ ์๋ค.
app.use(
session({
secret: '@tata',
resave: false,
saveUninitialized: true,
cookie: {
domain: 'localhost',
path: '/',
maxAge: 24 * 6 * 60 * 10000,
sameSite: 'none',
httpOnly: false,
secure: true,
},
})
);
์ธ์
๊ฐ์ฒด๋ req.session
์ผ๋ก ์ ๊ทผํ์ฌ
์์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ๋ถ๋ฌ์ฌ ์ ์๋ค.
// ์ฟ ํค์ ๋ค๋ฅด๊ฒ res๊ฐ ์๋๋ผ req์ ์์ฑํด์ผ ํ๋ค.
// ์ ํด์ง ์ฌ์ฉ๋ฒ์ด๋ ์ฃผ์ํ๊ธฐ!!
req.session.sessionId = userInfo.id
์น์
์ญ์ ๋ destroy
๋ก ํ๋ฉด ๋๋ค.
// ์น์
์ญ์ ์์
req.session.destroy();
๐ MDN - Set-Cookie Attributes ์ฟ ํค
๐ GitHub: express-session ์ธ์