๐ ํด์ฑ ๐ฅ ์ฟ ํค ๐ ์ธ์
๐ ํด์ฑ
ํด์ ํ ์ด๋ธ์์ ๋ค๋ฃจ์๋ ์ ์ด ์๋ Hash!
ํค(Key) ๊ฐ์ ํด์ ํจ์(Hash Function)๋ผ๋ ์์์ ๋์ ์์ผ ๊ณ์ฐํ ํ ๋์จ ๊ฒฐ๊ณผ๋ฅผ ์ฃผ์๋ก ์ฌ์ฉํ์ฌ ๋ฐ๋ก ๊ฐ(Value)์ ์ ๊ทผํ๊ฒ ํ ์ ํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์ธ์ฆ์์์ ํด์ฑ์ด๋ ๊ฒฐ๊ตญ ์ด๋ค ๊ฐ์ "์์์ ์ฐ์ฐ"์ ์ ์ฉํด ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ณํ, ์ฆ ์ํธํํ๋ ๊ณผ์ ์ ๋งํ๋ ๊ฒ์ด๋ผ ํ ์ ์๋ค.
๐ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ด ๊ฐ์ถฐ์ผ ํ ์กฐ๊ฑด
1) ๋ชจ๋ ๊ฐ์ ๋ํด ํด์๊ฐ์ ๊ณ์ฐํ๋๋ฐ ์ค๋ ๊ฑธ๋ฆฌ์ง ์์์ผ ํ๋ค.
2) ์ต๋ํ ํด์ ๊ฐ์ ํผํด์ผ ํ๋ฉฐ, ๋ชจ๋ ๊ฐ์ ๊ณ ์ ํ ํด์ ๊ฐ์ ๊ฐ์ง๋ค.
3) ์์ฃผ ์์ ๋จ์์ ๋ณ๊ฒฝ์ด๋ผ๋ ์์ ํ ๋ค๋ฅธ ํด์ ๊ฐ์ ๊ฐ์ ธ์ผ ํ๋ค.
๐ง Salt
๊ทธ๋ฌ๋ ์ฌ์ค ์๋ฒฝํ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ, ์๋ฒฝํ ์ํธํ๋ ์๋ค. ๋ฌผ๋ก ํด์ฑํจ์๋ ์ญํจ์๊ฐ ์กด์ฌํ์ง ์๋ ํจ์๋ก ๋ง๋๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์ง๋ง, ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๊ธฐ๋กํด๋๊ณ ์ถ์ ํ๋ ๊ฒ๊น์ง ๋ง์ ์๋ ์๋ค. ํด์ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ค ์ ์๋ ๊ฐ๋ค์ ๋๋์ผ๋ก ์ ์ฅํด๋์ ํ์ธ ๋ ์ธ๋ณด์ฐ ํ
์ด๋ธ
์ด๋ ๊ฒ๋ ์กด์ฌํ๋ค...!
๊ทธ๋์! ์๋ณธ๊ฐ์ ์์๋ก ์ฝ์๋ ๋ณ๋์ ๋ฌธ์์ด์ ์ถ๊ฐํด ๊ธฐ์กด ํด์ ๊ฐ๊ณผ ์ ํ ๋ค๋ฅธ ํด์๊ฐ์ ๋ฐํํด ์๊ณ ๋ฆฌ์ฆ์ด ๋ ธ์ถ๋๋๋ผ๋ ์๋ณธ๊ฐ์ ๋ณดํธํ๋ค. ์ด ๋ ์ถ๊ฐํ๋ ๋ณ๋์ ๊ฐ์ salt๋ผ๊ณ ํ๋ค!
โ๏ธ Salt์ ๋ํด ์ฃผ์ํด์ผ ํ ์ฌํญ
salt๋ ์ฌ์ฌ์ฉํด์๋ ์ ๋๋ฉฐ, ์ฌ์ฉ์ ๊ณ์ ์ ์์ฑํ๊ณ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ณ๊ฒฝํ ๋๋ง๋ค ์๋ก์ด ์์์ salt๋ฅผ ์ฌ์ฉํด ํด์ฑํด์ผ ํ๋ค. ๋, salt๋ ๋น์ฐํ DB ์ ์ ํ ์ด๋ธ์ ๊ฐ์ด ์ ์ฅํ๋ค!
๐ฅ ์ฟ ํค
์ฒ์์ ์ฟ ํค๋ฅผ ํ์ตํ ๋, ์ธ์ฆ๊ณผ ์ฎ์ด์ ํ์ตํ์ด์ ์ฟ ํค๋ฅผ ์ธ์
, ํ ํฐ
๊ณผ ๋น์ทํ๊ฒ ์ธ์ฆ ๋ฐฉ์ ์์ฒด๋ก ์ดํดํ์๋ค. ๊ทธ๋ฌ๋ ์๋ฐํ ๋งํ๋ฉด ์ฟ ํค๋ ์ธ์ฆ ๋ฐฉ์์ด๋ผ๊ธฐ๋ณด๋ค๋ ์๋ฒ์์ ํด๋ผ์ด์ธํธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ฐฉ๋ฒ ์ค ํ๋์ด๋ค. ๋ค๋ง ์ธ์ฆ ๊ณผ์ ์ ํ์ฉ๋๋ ๊ฒ!
HTTP ์ฟ ํค(์น ์ฟ ํค, ๋ธ๋ผ์ฐ์ ์ฟ ํค)๋ ์๋ฒ๊ฐ ์ฌ์ฉ์์ ์น ๋ธ๋ผ์ฐ์ ์ ์ ์กํ๋ ์์ ๋ฐ์ดํฐ ์กฐ๊ฐ์ ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ๊ทธ ๋ฐ์ดํฐ ์กฐ๊ฐ๋ค์ ์ ์ฅํด ๋์๋ค๊ฐ, ๋์ผํ ์๋ฒ์ ์ฌ ์์ฒญ ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ์ ์กํฉ๋๋ค. ์ฟ ํค๋ ๋ ์์ฒญ์ด ๋์ผํ ๋ธ๋ผ์ฐ์ ์์ ๋ค์ด์๋์ง ์๋์ง๋ฅผ ํ๋จํ ๋ ์ฃผ๋ก ์ฌ์ฉํฉ๋๋ค. ์ด๋ฅผ ์ด์ฉํ๋ฉด ์ฌ์ฉ์์ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค. ์ํ๊ฐ ์๋(stateless) HTTP ํ๋กํ ์ฝ์์ ์ํ ์ ๋ณด๋ฅผ ๊ธฐ์ต์์ผ์ฃผ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ชจ์ชผ๋ก ์ฟ ํค๋ฅผ ํ์ฉํ๋ฉด ์๋ฒ๋ ํด๋ผ์ด์ธํธ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด ์ ์ฅํ ์ ์๊ณ , ๋ ํด๋น ์ ๋ณด๋ฅผ ๋ค์ ๊ฐ์ ธ์ฌ ์๋ ์๋ค! (๋ํ ์ฟ ํค๋ ๋ฐ๋ก ์ญ์ ํ์ง ์์ผ๋ฉด ๊ณ์ํด์ ๋ณด์กด๋๋ค.) ๊ทธ๋ฌ๋ ๋น์ฐํ๊ฒ๋ ์๋ฌด ๋๋ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ ๊ฒ์ ์๋๋ค. ์ด ์กฐ๊ฑด๋ค์ ๋ํ๋ธ ๊ฒ๋ค์ด ๋ฐ๋ก ์ฟ ํค์ต์ ์ด๋ค!
๐ซ ์ฟ ํค ์ต์
// example
cookie: {
domain: 'localhost',
path: '/',
maxAge: 24 * 6 * 60 * 10000,
sameSite: 'none',
httpOnly: true,
secure: true,
},
- Domain: ์ฟ ํค์ ๋๋ฉ์ธ ์ต์ ๊ณผ ์๋ฒ์ ๋๋ฉ์ธ์ด ์ผ์นํด์ผ๋ง ์ฟ ํค๋ฅผ ์ ์กํ ์ ์๋ค.
- Path: ์ฟ ํค์ path ์ต์ ๊ณผ ์๋ฒ์ ์ธ๋ถ๊ฒฝ๋ก๊ฐ ์ผ์นํ๋ ๊ฒฝ์ฐ ์ฟ ํค๋ฅผ ์ ์กํ ์ ์๋ค.
- MaxAge or Expires: ์ฟ ํค์ ์ ํจ๊ธฐ๊ฐ ์ค์
- HttpOnly: ์คํฌ๋ฆฝํธ์ ์ฟ ํค์ ๊ทผ ๊ฐ๋ฅ ์ฌ๋ถ ๊ฒฐ์ , false๋ก ์ค์ ๋์ด ์๋ ๊ฒฝ์ฐ ์คํฌ๋ฆฝํธํ๊ทธ๋ก ์ฟ ํค์ ์ ๊ทผ ๊ฐ๋ฅํ๋ค. (XSS ๊ณต๊ฒฉ์ ์ทจ์ฝํ๋ฏ๋ก, ๋ฏผ๊ฐํ ๊ฐ์ธ์ ๋ณด๋ ๋ด์ง ์๋ ๊ฒ์ด ์ข๋ค.)
- Secure: ํด๋น ์ต์ ์ด true๋ก ์ค์ ๋์ด ์๋ ๊ฒฝ์ฐ, https ํ๋กํ ์ฝ์์๋ง ์ฟ ํค ์ ์ก ๊ฐ๋ฅํ๋ค.
- SameSite: CORS ์์ฒญ์ ๊ฒฝ์ฐ, ์ต์ ๋ฐ ๋ฉ์๋์ ๋ฐ๋ผ ์ฟ ํค ์ ์ก ์ฌ๋ถ ๊ฒฐ์ . (Lax-'GET' ๋ฉ์๋์ ๋ํด์๋ง ์ฟ ํค ์ ์ก ๊ฐ๋ฅ, Strict-CrossOrigin์ด ์๋ sameSite์ ๋ํด์๋ง ์ฟ ํค ์ ์ก ๊ฐ๋ฅ, None-ํญ์ ์ฟ ํค์ ์ก ๊ฐ๋ฅํ์ง๋ง ์ฟ ํค์ต์ ์ค secure ์ต์ ์ด ํ์ฑํ๋์ด์ผ ํจ)
์ฟ ํค๋ฅผ ์ด๋์ ํ์ฉํ ๊ฒ์ด๋!
์ธ์ ๊ด๋ฆฌ(Session management)
์๋ฒ์ ์ ์ฅํด์ผ ํ ๋ก๊ทธ์ธ, ์ฅ๋ฐ๊ตฌ๋, ๊ฒ์ ์ค์ฝ์ด ๋ฑ์ ์ ๋ณด ๊ด๋ฆฌ
๊ฐ์ธํ
์ฌ์ฉ์ ์ ํธ, ํ ๋ง ๋ฑ์ ์ธํ
ํธ๋ํน
์ฌ์ฉ์ ํ๋์ ๊ธฐ๋กํ๊ณ ๋ถ์ํ๋ ์ฉ๋
๐ ์ธ์
์ฟ ํค๋ ์ฌ์ค ๊ทธ ์์ฒด๋ก ์ธ์ฆ ์๋จ์ ์๋๋ผ๋ ์ฌ์ค์ ์ดํด๋ณด์๋ค. ๊ฒ๋ค๊ฐ ํด๋ผ์ด์ธํธ์ ์ ๋ณด๋ค์ ์ ์ฅํ๋๋ฐ ์ด๋ ๋ณด์์ ๊ทธ๋ฆฌ ๊ฐ๋ ฅํ ์ ํ์ด ์๋๋ค! ์ด์ ๋ํ ๋์์ผ๋ก ์ฐ๋ฆฌ๋ ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ์ ์์๋ณผ ๊ฒ์ด๋ค!
์ฟ ํค๊ฐ ํด๋ผ์ด์ธํธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ์์๋ ๋ฐ์ดํฐ๋ค์ ์๋ฒ์ ์์ ํ๊ฒ ์ ์ฅํ๋ค! ์ธ์ ์คํ ๋ฆฌ์ง์ ์ ๋ณด๋ค์ ์ ์ฅํ๊ณ ๋์ ํด๋ผ์ด์ธํธ์๋ ์ธ์ id๋ง์ ์ ๋ฌํด์ฃผ๋ ๊ฒ์ด๋ค! ๋ช ํํ ๋ฐ์ง๋ฉด ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์ฑ๊ณตํ ์ํ๊ฐ ์ธ์ ์ ํด๋นํ๊ณ , ์ธ์ ์ด ํ์ฑํ๋๋ฉด ์ธ์ ์์ด๋๊ฐ ๋ฐ๊ธ๋๊ณ , ์ด ์ธ์ ์ฑ๊ณต์ ์ฆ๋ช ํ ์๋จ์ผ๋ก ํด๋ผ์ด์ธํธ๋ ์ธ์ ์์ด๋๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ฟ ํค์๋ ์ด id๋ง ์ ์ฅ์ ํด์ฃผ๋ ๊ฒ์ด๋ค!
์ธ์ ์คํ ๋ฆฌ์ง๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ ๋ค์ํ๋ฐ, 1) ์๋ฒ ์์ฒด์ ์ ์ฅ์ ํ ์๋ ์๊ณ , 2) ํ์ผ๋ก ์ ์ฅ์ ํ ์๋ ์๊ณ , 3) DB์ ์ ์ฅ์ ํ ์๋ ์๋ค. 1)์ ๊ฒฝ์ฐ ์๋ฒ๊ฐ ์ข ๋ฃ๋๋ฉด ์ ๋ณด๋ค์ด ๋ชจ๋ ์ฌ๋ผ์ง๋ค๋ ์ทจ์ฝ์ ์ด ์กด์ฌํ๋ฉฐ, 2)์ ๊ฒฝ์ฐ ๋์์ ์์ ์ด ๋ถ๊ฐํ๋ค๋ ๋จ์ ์ด ์กด์ฌํ๋ค!
Session์ ๊ธฐ๋ณธ ๋ก์ง
ํด๋ผ์ด์ธํธ๋ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์์ฒญ ๋ฐ๋์ ๋ด์ ๋ก๊ทธ์ธ ํฌ์คํธ ์์ฒญ์ ๋ณด๋ธ๋ค
axios
.post(
"https://localhost:4000/users/login",
{
userId: this.state.username,
password: this.state.password,
},
{
"Content-Type": "application/json",
withCredentials: true,
}
)
์ฌ๊ธฐ์ ์ ๊น withCredentials์ ๋ํด ์ง๊ณ ๋์ด๊ฐ์! ๊ธฐ๋ณธ์ ์ผ๋ก withCredentials
๋ CORS ์ต์
์ด๋ค. ๊ฐ์ origin์์ httpํต์ ์ ํ๋ ๊ฒฝ์ฐ ์์์ cookie๊ฐ request header์ ๋ค์ด๊ฐ๋ค. ํ์ง๋ง origin์ด ๋ค๋ฅผ ๊ฒฝ์ฐ๋ ๊ทธ๋ ์ง ์๋ค. ์๋์ผ๋ก ์ฟ ํค๋ฅผ ํค๋์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค. ์ด๋ ํ์ํ ๊ฒ์ด ํด๋ผ์ด์ธํธ์์๋ withCredentials: true
, ์๋ฒ์์๋ Access-Control-Allow-Credentials : true
์ด๋ค!
๋ก๊ทธ์ธ ์์ฒญ์ ๋ฐ์ ์๋ฒ๋ ์ธ์ ์ ํ์ฑํํ๋ค!
req.session.save(function () {
req.session.userId = userInfo.userId;
res.json({ data: userInfo, message: "ok" });
});
Session.save(callback)
ํด๋น ๋ฉ์๋๋ ์ธ์ ์ ๋ค์ ์ ์ฅ์์ ์ ์ฅํ๊ณ , ์ ์ฅ์์ ๋ด์ฉ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ด์ฉ์ผ๋ก ๋ฐ๊พผ๋ค. ์ธ์ ์ ์คํ ์ด์ ์ ์ฅํ๊ณ ๋๋ฉด callback์ผ๋ก ๋๊ฒจ์ค ํจ์๊ฐ ์คํ๋๋ค. ์ด ๋ฉ์๋๋ฅผ ์ฐ์ง ์์ผ๋ฉด, ๋ฐ์ดํฐ๋ฅผ session store์ ์ ์ฅํ๋ ๊ฒ๋ณด๋ค redirect๊ฐ ๋จผ์ ์คํ๋์ด ๋ก๊ทธ์ธ ์ํ๊ฐ ์ ์ง๋์ง ์๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์๋ค!
์๋ฒ๋ ์ดํ์ ์์ฒญ์ ๋ฐ์ ์ session์ ํ์ธํด ์ธ์ฆ๊ณผ์ ์ ๊ฑฐ์น๋ค.
if (!req.session.userId) {
res.status(400).send({ data: null, message: "not authorized" });
} else {
const result = await Users.findOne({
where: { userId: req.session.userId },
}).catch((err) => res.json(err));
res.status(200).json({ data: result, message: "ok" });
}
์ฟ ํค์ ์ธ์ , ์ ๊ฒฉ ๋น๊ต!
- ์ ์ฅ์ ์ด๋์? ์ฟ ํค๋ ํด๋ผ์ด์ธํธ, ์ธ์ ์ ์๋ฒ
- ์ฅ์ ์? ์ฟ ํค๋ ์๋ฒ์ ๋ถ๋ด ์ ์ค, ์ธ์ ์ ์ ๋ขฐํ ๋งํ ์ ์ ์ธ์ง ์๋ฒ์์ ์ถ๊ฐ๋ก ํ์ธ ๊ฐ๋ฅ! (๋ ์์ ํจ)
- ๋จ์ ์? ์ฟ ํค๋ ๊ทธ ์์ฒด๋ก๋ ์ธ์ฆ์ด ์๋, ์ธ์ ์ ๋ถ์ฐ์ ๋ถ๋ฆฌํจ
์ฐธ๊ณ ๋ฌธ์
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ ํด์ฑ ๐ฅ ์ฟ ํค ๐ ์ธ์ ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@9rganizedchaos/์ฟ ํค-์ฟ ํค-์ฟ ํค์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค