Jieunny์ ๋ธ๋ก๊ทธ
S3) Unit 7. [์ค์ต] Cookie๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ ๋ณธ๋ฌธ
S3) Unit 7. [์ค์ต] Cookie๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ
Jieunny 2023. 3. 7. 15:00๐ฃ Cookie ์ฌ์ฉํด์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ
๏ผ Client
๐ญ. ํ ์คํธ ์ผ์ด์ค
Auth - Client
โ ๐งฉ ์ ์ ์ ๋ณด๊ฐ ์ถฉ๋ถํ์ง ์์ ์ํ์์ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅผ ์ ์๋ฌ๋ฉ์์ง๊ฐ ๋ํ๋์ผ ํฉ๋๋ค. (361 ms)
โ ๐งฉ ๋ก๊ทธ์ธ ๋ฒํผ ํด๋ฆญ ์ ์ฑ๊ณต์ ์ผ๋ก ๋ก๊ทธ์ธ๋์ด์ผ ํฉ๋๋ค. (204 ms)
โ ๐งฉ ๋ก๊ทธ์์ ๋ฒํผ ํด๋ฆญ ์ ์ฑ๊ณต์ ์ผ๋ก ๋ก๊ทธ์์๋์ด์ผ ํฉ๋๋ค. (144 ms)
โ ๐งฉ ์กด์ฌํ์ง ์๋ ์ ์ ์ ์ ๋ณด๋ก ๋ก๊ทธ์ธํ ์ ์๋ฌ๋ฉ์์ง๊ฐ ๋ํ๋์ผ ํฉ๋๋ค. (66 ms)
๐ฎ. ํ์ผ ๊ตฌ์กฐ
src
ใด pages
ใด Login.js : ์๋ฒ๋ก ๋ก๊ทธ์ธ ์์ฒญ ๋ณด๋ด๊ธฐ
ใด MyPage.js : ์๋ฒ๋ก ๋ก๊ทธ์์ ์์ฒญ ๋ณด๋ด๊ธฐ
ใด App.js : ์ด๊ธฐํ๋ฉด ๋ ๋๋ง(Login ํ์ด์ง์ธ์ง MyPage ์ธ์ง)
๐ฏ. ์ฝ๋ ๊ตฌํ
๐ App.js
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Login from './pages/Login';
import Mypage from './pages/Mypage';
import React, { useEffect, useState } from 'react';
import axios from 'axios';
// ๋ชจ๋ ์์ฒญ์ withCredentials๊ฐ true๋ก ์ค์ ๋ฉ๋๋ค.
axios.defaults.withCredentials = true;
function App() {
const [isLogin, setIsLogin] = useState(false);
const [userInfo, setUserInfo] = useState(null);
const authHandler = () => {
// ์๋ฒ์ userInfo์์ ๋ฐ์์จ ์ ์ ์ ๋ณด๊ฐ ์์ผ๋ฉด
// ์๋ก ๊ณ ์นจํด๋ ๋ก๊ทธ์ธ์ด ์ ์ง๋๋๋ก ํ๋ค(๋ก๊ทธ์ธ ์ ์ง ์ฒดํฌํ์ ๋)
/*
TODO: ์ด๊ธฐ ํ๋ฉด ๋ ๋๋ง์, ์๋ฒ์ ์ ์ ์ ๋ณด๋ฅผ ์์ฒญํ์ฌ Login ๋๋ Mypage๊ฐ ๋ ๋๋ง๋๋๋ก ๊ตฌํํฉ๋๋ค.
return axios
.get(์ ์ ์ ์ ๋ณด๋ฅผ ๋ด๋นํ๋ endpoint)
.then((res) => {
์ธ์ฆ์ ์ฑ๊ณตํ๋ค๋ฉด ์๋ต์ผ๋ก ๋ฐ์ ๋ฐ์ดํฐ๊ฐ Mypage์ ๋ ๋๋ง๋๋๋ก State๋ฅผ ๋ณ๊ฒฝํ์ธ์.
})
.catch((err) => {
์ธ์ฆ์ ์คํจํ๋ค๋ฉด ๊ทธ์ ๋ํ ์๋ฌ ํธ๋ค๋ง์ ๊ตฌํํ์ธ์.
});
*/
return axios
.get("http://localhost:4000/userinfo");
// ์๋ฒ์ userinfo๋ก ์ ์ ์ ๋ณด๋ฅผ ์์ฒญํ๋ค.
.then((res) => {
// ์ ์ ์ ๋ณด๋ฅผ ์ ๋ฐ์์์ ๊ฒฝ์ฐ
setIsLogin(true)
// ๋ก๊ทธ์ธ ์ฑ๊ณต -> ์๋ก๊ณ ์นจํด๋ ๋ก๊ทธ์์ ๋์ง ์๋๋ค.
setUserInfo(res.data)
// ์ ์ ์ ๋ณด ๋ฐ๊ฟ์ฃผ๊ธฐ
})
.catch((err) => {
// ์ ์ ์ ๋ณด๋ฅผ ์ ๋๋ก ๋ฐ์์ค์ง ๋ชปํ์ ๊ฒฝ์ฐ
console.log(err.response.data)
});
};
useEffect(() => {
// ์ปดํฌ๋ํธ ์์ฑ ์ ์๋ ํจ์๊ฐ ์คํ๋ฉ๋๋ค.
authHandler();
}, []);
return(
...
// ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ์ ์๋ง์ props๋ฅผ ๋ด๋ ค์ฃผ์ด์ผ ํ๋ค.
);
}
๐ Login.js
import React, { useState } from 'react';
import axios from 'axios';
export default function Login({setUserInfo, setIsLogin}) {
const [loginInfo, setLoginInfo] = useState({
// input ์ฐฝ์ ์์ด๋, ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ๋ฉด ์
๋ฐ์ดํธ ๋๋ค.
userId: '',
password: '',
});
const [checkedKeepLogin, setCheckedKeepLogin] = useState(false);
// '๋ก๊ทธ์ธ ์ ์งํ๊ธฐ' ์ฒดํฌ ์ํ๋ฅผ ์๋ฏธํ๋ค.
const [errorMessage, setErrorMessage] = useState('');
// ์๋ฌ ๋ฐ์ ์ ๋ก๊ทธ์ธ ๋ฒํผ ๋ฐ์ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
const handleInputValue = (key) => (e) => {
// key๋ก id์ password๋ฅผ ๊ตฌ๋ถํ๊ณ , input์ด ๋ณํ ๋ ๋ง๋ค ๋ฐ์์จ๋ค.
setLoginInfo({ ...loginInfo, [key]: e.target.value });
};
const loginRequestHandler = () => {
/*
TODO: Login ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ง๊ณ ์๋ state๋ฅผ ์ด์ฉํด ๋ก๊ทธ์ธ์ ๊ตฌํํฉ๋๋ค.
๋ก๊ทธ์ธ์ ํ์ํ ์ ์ ์ ๋ณด๊ฐ ์ถฉ๋ถํ ์ ๊ณต๋์ง ์์๋ค๋ฉด ์๋ฌ๋ฉ์์ง๊ฐ ๋ํ๋๋๋ก ๊ตฌํํ์ธ์.
return axios
.post(login์ ๋ด๋นํ๋ endpoint)
.then((res) => {
๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ค๋ฉด ์๋ต์ผ๋ก ๋ฐ์ ๋ฐ์ดํฐ๊ฐ Mypage์ ๋ ๋๋ง๋๋๋ก State๋ฅผ ๋ณ๊ฒฝํ์ธ์.
})
.catch((err) => {
๋ก๊ทธ์ธ์ ์คํจํ๋ค๋ฉด ๊ทธ์ ๋ํ ์๋ฌ ํธ๋ค๋ง์ ๊ตฌํํ์ธ์.
});
*/
if(!loginInfo.userId || !loginInfo.password){
// ์์ด๋๋ ํจ์ค์๋ ์ค ํ๋๋ผ๋ ์
๋ ฅ๋์ง ์์์ ๊ฒฝ์ฐ
setErrorMessage('์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.');
// ์์ฒญ ๋ณด๋ผ ํ์ ์์ด ๋ฐ๋ก ๋ฆฌํด(์๋ฌ๋๊น)
return;
}
return axios
.post("http://localhost:4000/login", {loginInfo, checkedKeepLogin})
// ๋ก๊ทธ์ธ์ ์ฒ๋ฆฌํ๋ ์๋ํฌ์ธํธ๋ฅผ ๋ณด๋ด์ค๋ค.
// ์๋ํฌ์ธํธ ๋ค์ ์ธ์๋ก req.body๋ฅผ ๋ณด๋ด์ค๋ค -> ์๋ฒ์ login.js์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ค์ด์ฃผ๋ ๊ฒ
.then((res) => {
// ์๋ต์ ์ ๋ฐ์์์ ๋
setUserInfo(res.data)
setIsLogin(true)
console.log(res.data);
// ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ์ ๊ฒฝ์ฐ ์๋ฌ๋ฉ์์ง๋ฅผ ์ง์์ค๋ค.
setErrorMessage("")
})
.catch((err) => {
// ์๋ต์ ์ ๋๋ก ๋ฐ์์ค์ง ๋ชปํ์ ๋
console.log(err.response.data)
setErrorMessage("๋ก๊ทธ์ธ์ ์คํจํ์ต๋๋ค.")
})
};
return (
...
);
}
๐ MyPage.js
import axios from 'axios';
import React from 'react';
export default function Mypage({ userInfo, setIsLogin ,setUserInfo }) {
// ๋ก๊ทธ์ธ์ด ์ฑ๊ณตํ์ ๋ ๋จ๋ ํ์ด์ง(๋ก๊ทธ์์ ๋ฒํผ์ด ์๋ค)
const logoutHandler = () => {
// ๋ก๊ทธ์์ ๋ฒํผ์ ๋๋ ์ ๋ ์๋ํ ํจ์
/*
TODO: Logout ๋ฒํผ์ ๋๋ ์ ์ Login ํ์ด์ง๋ก ๋์๊ฐ ์ ์๋๋ก ๊ตฌํํ์ธ์.
return axios
.post(logout์ ๋ด๋นํ๋ endpoint)
.then((res) => {
๋ก๊ทธ์์์ ์ฑ๊ณตํ๋ค๋ฉด App์ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ธ์.
})
.catch((err) => {
๋ก๊ทธ์์์ ์คํจํ๋ค๋ฉด ๊ทธ์ ๋ํ ์๋ฌ ํธ๋ค๋ง์ ๊ตฌํํ์ธ์.
});
*/
return axios
.post("http://localhost:4000/logout")
// ์๋ฒ์ logout์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ์ ์๊ฒ ์๋ํฌ์ธํธ๋ฅผ ์์ฑํด์ค๋ค.
.then((res) => {
setIsLogin(false);
setUserInfo(null);
})
.catch((err) => {
console.log(err);
})
};
return(
...
);
}
๏ผ Server
๐ญ. ํ ์คํธ ์ผ์ด์ค
POST /login
โ ๐ฉ db์ ์กด์ฌํ๋ ์ ์ ๊ฐ ์๋๋ผ๋ฉด, ์ํ ์ฝ๋ 401์ ํจ๊ป Not Authorized๋ผ๋ ๋ฉ์ธ์ง๊ฐ ์๋ต์ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
โ ๐ฉ ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ค๋ฉด /userinfo๋ก ๋ฆฌ๋ค์ด๋ ํธ ๋์ด์ผ ํฉ๋๋ค.
โ ๐ฉ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ผ์์ ์ผ๋ก ์ ์งํ๋ ์์ฒญ์ด๋ผ๋ฉด Session Cookie๋ฅผ ๋ณด๋ด์ผํฉ๋๋ค.
POST /login
โ ๐ฉ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ๋ ์์ฒญ์ด๋ผ๋ฉด Session Cookie๊ฐ ์๋ Persistent Cookie๋ฅผ ๋ณด๋ด์ผํฉ๋๋ค.
Cookie Option
โ ์ฟ ํค ์ต์
์ค Domain ์ต์
์ `localhost`๋ก ์ค์ ๋์ด์ผ ํฉ๋๋ค
โ ์ฟ ํค ์ต์
์ค Path ์ต์
์ `/`๋ก ์ค์ ๋์ด์ผ ํฉ๋๋ค
โ ์ฟ ํค ์ต์
์ค HttpOnly ์ต์
์ด ์ค์ ๋์ด์ผ ํฉ๋๋ค
โ ์ฟ ํค ์ต์
์ค Secure ์ต์
์ด ์ค์ ๋์ด์ผ ํฉ๋๋ค
โ ์ฟ ํค ์ต์
์ค SameSite ์ต์
์ `none`์ผ๋ก ์ค์ ๋์ด์ผ ํฉ๋๋ค
GET /userinfo
GET /userinfo 401 1.372 ms - 14
โ ๐ฉ ์ฟ ํค์ cookieId๊ฐ ์๋ค๋ฉด, ์ํ ์ฝ๋ 401์ ํจ๊ป Not Authorized๋ผ๋ ๋ฉ์ธ์ง๊ฐ ์๋ต์ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
GET /userinfo 401 0.806 ms - 14
โ ๐ฉ ์ฟ ํค์ ์ ์ฅ๋ cookieId๊ฐ ์ ์ ์ ๋ณด์ ์ผ์นํ์ง ์๋๋ค๋ฉด, ์ํ ์ฝ๋ 401์ ํจ๊ป Not Authorized๋ผ๋ ๋ฉ์ธ์ง๊ฐ ์๋ต์ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
GET /userinfo 200 1.657 ms - 295
โ ๐ฉ ์ฟ ํค์ ์ ์ฅ๋ cookieId๊ฐ ์ ์ ์ ๋ณด์ ์ผ์นํ๋ค๋ฉด, ์ ์ ์ ๋ณด๊ฐ ์๋ต์ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
GET /userinfo 200 0.819 ms - 295
โ ๐ฉ ์๋ต์ ํฌํจ๋ ์ ์ ์ ๋ณด์ ๋น๋ฐ๋ฒํธ๊ฐ ๋ด๊ฒจ์์ง ์์์ผ ํฉ๋๋ค.
POST /logout
POST /logout 205 1.049 ms - 0
โ ๐ฉ ๋ก๊ทธ์์ ์์ฒญ ์ 205 ์ํ์ฝ๋๋ก ์๋ตํด์ผ ํฉ๋๋ค.
โ ๐ฉ ๋ก๊ทธ์์ ์์ฒญ ์ ์ฟ ํค๋ฅผ ์ด๊ธฐํํด์ผ ํฉ๋๋ค.
๐ฎ. ํ์ผ ๊ตฌ์กฐ
src
ใด controllers
ใด users
ใด login.js : ์ฟ ํค๋ฅผ ๋ฐ๊ธํ๋ค.
ใด logout.js : ์ฟ ํค๋ฅผ ์ญ์ ํ๊ณ , ์ํ์ฝ๋๋ก 205๋ฅผ ์ ๋ฌํ๋ค(205 : Reset Content)
ใด userinfo.js : ์ฟ ํค๋ฅผ ๊ฒ์ฆํด์ ์ ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ค.
ใด index.js
ใด controllers
ใด users
ใดdata.js : ๋ก๊ทธ์ธ ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์๋ ํ์ผ
๐ฏ. ์ฝ๋ ๊ตฌํ
๐ login.js
const { USER_DATA } = require('../../db/data');
//๋ก๊ทธ์ธ์ด ์ฑ๊ณต์ ์ผ๋ก ์ด๋ฃจ์ด์ ธ์ผ ์ฟ ๊ธฐ๊ฐ ๋ง๋ค์ด์ง๋ค!!
module.exports = (req, res) => {
const { userId, password } = req.body.loginInfo;
const { checkedKeepLogin } = req.body;
const userInfo = {
...USER_DATA.filter((user) => user.userId === userId && user.password === password)[0],
// data.js์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ req.body๋ก ๋ค์ด์จ ์์ด๋์ ํจ์ค์๋์ ๊ฐ์ ์ ๋ค๋ง ๋จ๊ธฐ๊ณ ์๋ค.
// ์์ผ๋ฉฐ ๋น ๊ฐ์ฒด ๋ฆฌํด
};
const cookiesOption = {
domain: 'localhost',
path: '/',
// ์ ํจ๊ธฐ๊ฐ์ ๋ก๊ทธ์ธ ์ฒดํฌ ์ฌ๋ถ์ ๋ฐ๋ผ ๋ฌ๋ผ์งํ
๋ ์ผ๋จ ํจ์คํฉ๋๋ค.
// secure๋ ์ผ๋จ ํจ์คํ๊ณ , sameSite ์ต์
์ ์์ฑํ ๋ ๋ค์ ํ์ธํฉ์๋ค.
httpOnly: true,
// sameSite ์ต์
์ ์ค์ ๊ฐ์ ํ์ธํ๋ฉด์ ์ด๋ค ์ต์
์ ์ค์ ํ๋ฉด ์ข์์ง ์ดํด๋ด
์๋ค.
// Lax : Get ์์ฒญ๋ง ์ฟ ํค ์ ์ก. ๊ทธ๋ฐ๋ฐ ํด๋ผ์ด์ธํธ์์ ์์ด๋๋ ๋น๋ฐ๋ฒํธ๋ฅผ POST๋ก ๋ณด๋ด์ฃผ๊ณ ์์ผ๋ฏ๋ก ์ง๊ธ ์ฌ์ฉํ๊ธฐ์ ๋ถ์ ํฉํด์.
// Strict : same-site๋ง ๊ฐ๋ฅ. ๊ทธ๋ฐ๋ฐ ํด๋ผ์ด์ธํธ๋ http ํ๋กํ ์ฝ + 3000๋ฒ ํฌํธ, ์๋ฒ๋ https ํ๋กํ ์ฝ + 4000๋ฒ ํฌํธ๋ก same-site๊ฐ ์๋๋๋ค. ๋ฐ๋ผ์ ์ด ์ต์
๋ ๋ถ์ ํฉํฉ๋๋ค.
// ๋ฐ๋ผ์ 'none'์ด ๊ฐ์ฅ ์ ํฉํ ์ต์
๊ฐ์
๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด ์ต์
์ ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ secure ์ต์
์ด ํ์ํ๋ค๊ณ ํด์. secure ์ต์
๋ ๊ฐ์ด ์์ฑํด์ค์๋ค.
sameSite: 'none',
secure: true,
}
if(userInfo.id === undefined){
// ๋ก๊ทธ์ธ ์คํจํ๋ฉด(๋ก๊ทธ์ธ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ) ์๋ฌ ๋ฉ์์ง ๋ณด๋ด๊ณ
// userInfo๋ ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ๋น ๊ฐ์ฒด๊ฐ ๋ค์ด์ค๋ฏ๋ก ๋ถ๊ธฐ๋ฅผ ๋๋ ์ ์ฒ๋ฆฌํด์ค๋ค.
res.status(401).send('Not Authorized');
} else if (checkedKeepLogin === true) {
// ๋ก๊ทธ์ธ์ ์ ์งํ๊ณ ์ถ์ ๊ฒฝ์ฐ, cookiesOption์ max-age ๋๋ expires ์ต์
์ ์ถ๊ฐ๋ก ์ค์ ํด์ฃผ๊ฒ ์ต๋๋ค.
// max-age ์ต์
์ผ๋ก ์์ฑํ๋ ๊ฒฝ์ฐ
cookiesOption.maxAge = 1000 * 60 * 30
// ๋จ์๋ ms(๋ฐ๋ฆฌ์ธ์ปจ๋ === 0.001์ด)์ด๋ ์ฃผ์ํ์ธ์! -> ์ด๋ ๊ฒ ์์ฑํ ๊ฒฝ์ฐ 30๋ถ๋์ ์ฟ ํค๋ฅผ ์ ์งํฉ๋๋ค.
// expires ์ต์
์ผ๋ก ์์ฑํ๋ ๊ฒฝ์ฐ์๋, ์ด๋ ๊ฒ ์์ฑํ์๋ฉด ๋ฉ๋๋ค.
cookiesOption.expires = new Date(Date.now() + (1000 * 60 * 30) )
// ์ง๊ธ ์๊ฐ + 30๋ถ ํ์ ์ฟ ํค๋ฅผ ์ญ์ ํ๋ค๋ ์๋ฏธ์
๋๋ค.
res.cookie('cookieId', userInfo.id, cookiesOption);
// express ์๋ฒ์ ์ฟ ํค ๋ณด๋ด๋ ๋ฐฉ๋ฒ(์ฟ ํค ์ด๋ฆ, ์ฟ ํค ๊ฐ, ์ฟ ํค ์ต์
)
} else {
// ๋ก๊ทธ์ธ์ ์ ์งํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ, max-age ๋๋ expires ์ต์
์ ์์ฑํ์ง ์์ ์ํ ๊ทธ๋๋ก ์ฟ ํค๋ฅผ ์ค์ ํฉ๋๋ค.
res.cookie('cookieId', userInfo.id, cookiesOption)
}
res.redirect("/userinfo")
// ์ฌ๊ธฐ์๋ ์ฟ ํค๋ฅผ ๋ฐ๊ธํ๊ธฐ๋ง ํ๊ณ userInfo์์ ํ์์ ๋ณด๋ฅผ ๋ณด๋ด์ฃผ๋ฏ๋ก
// userInfo๋ก ๋ฆฌ๋ค์ด๋ ํธ ํด์ค๋ค
/*
* TODO: ๋ก๊ทธ์ธ ๋ก์ง์ ๊ตฌํํ์ธ์.
*
* userInfo์๋ ์์ฒญ์ ๋ฐ๋๋ฅผ ์ด์ฉํด db์์ ์กฐํํ ์ ์ ์ ๋ณด๊ฐ ๋ด๊ฒจ์์ต๋๋ค. ์ฝ์์์ userInfo๋ฅผ ์ถ๋ ฅํด๋ณด์ธ์.
* ์ ์ ์ ์ ๋ณด๊ฐ ์ถ๋ ฅ๋๋ค๋ฉด ํด๋น ์ ์ ๊ฐ ์กด์ฌํ๋ ๊ฒ์์ผ๋ก ๋ก๊ทธ์ธ ์ฑ๊ณต์ ๋ํ ์๋ต์ ์ ์กํด์ผ ํฉ๋๋ค.
* ๋ง์ฝ undefined๊ฐ ์ถ๋ ฅ๋๋ค๋ฉด ํด๋นํ๋ ์ ์ ๊ฐ ์กด์ฌํ์ง ์๋ ๊ฒ์์ผ๋ก ๋ก๊ทธ์ธ ์คํจ์ ๋ํ ์๋ต์ ์ ์กํด์ผ ํฉ๋๋ค.
*
* ๋ก๊ทธ์ธ ์ฑ๊ณต ์์๋ ํด๋ผ์ด์ธํธ์ ์ฟ ํค๋ฅผ ์ ์กํด์ผํฉ๋๋ค. ์ฟ ํค์ cookieId์๋ userInfo.id๊ฐ ๋ด๊ฒจ์ผ ํฉ๋๋ค.
* ํ
์คํธ์ผ์ด์ค์์ ์๊ตฌํ๋ ์ฟ ํค ์ต์
์ ๋ชจ๋ ์ค์ ํ์ธ์.
* ์์์ฑ์๋ ์ฟ ํค๋ฅผ ๋ณด๋ด๋ ค๋ฉด max-age ๋๋ expires ์ต์
์ ์ค์ ํ์ธ์.
*
* ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ๋ก ์๋ต์ ๋ณด๋ด์ง์๊ณ ์๋ฒ์ /useinfo๋ก ๋ฆฌ๋ค์ด๋ ํธํด์ผ ํฉ๋๋ค.
* express์ res.redirect ๋ฉ์๋๋ฅผ ์ฐธ๊ณ ํ์ฌ ์๋ฒ์ /userinfo๋ก ๋ฆฌ๋ค์ด๋ ํธ ๋ ์ ์๋๋ก ๊ตฌํํ์ธ์.
*/
};
๐ userInfo.js
const { USER_DATA } = require('../../db/data');
module.exports = (req, res) => {
// login์์ ์ฟ ํค๊ฐ ์ ๋ง๋ค์ด์ก๋ค๋ฉด, ์ฟ ํค๋ฅผ ์์ฑํ ๋ ๋ฃ์ด ์ค userInfo.id๊ฐ ๋ค์ด์๋ค.
// ์ด ๊ฐ์ ์ฌ์ฉํด์ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌํด์ค ์ ์ ์ ๋ณด๋ฅผ ํํฐ๋งํ๋ค.
const cookieId = req.cookies.cookieId
const userInfo = {
...USER_DATA.filter((user) => user.id === cookieId)[0],
};
if (!cookieId || !userInfo.id){
// ์ ํจํ ์์ด๋๊ฐ ์๋๊ฒฝ์ฐ userInfo๊ฐ ๋น์ด์์ ์๋ ์๊ณ
// ์ฟ ํค๊ฐ ์์ ๋๋ userInfo ๊ฐ์ด ์ ๋๋ก ๋ค์ด์ค์ง ์๋๋ค. -> ๋ก๊ทธ์ธ ์คํจ
res.status(401).send('Not Authorized');
} else {
// ๋น๋ฐ๋ฒํธ๋ ๋ฏผ๊ฐํ ์ ๋ณด๋ผ์ ์ญ์ ํ์ ๋ณด๋ด์ผ ํฉ๋๋ค.
delete userInfo.password
res.send(userInfo)
}
/*
* TODO: ์ฟ ํค ๊ฒ์ฆ ์ฌ๋ถ์ ๋ฐ๋ผ ์ ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ ๋ก์ง์ ๊ตฌํํ์ธ์.
*
* ๋ก๊ทธ์ธ ์ ์ค์ ํ ์ฟ ํค๊ฐ ์กด์ฌํ๋ ์ง ํ์ธํด์ผ ํฉ๋๋ค.
* ์์ง ๋ก๊ทธ์ธ์ ํ์ง ์์๋ค๋ฉด ์ฟ ํค๊ฐ ์กด์ฌํ์ง ์์ ์ ์์ต๋๋ค.
* ์ฟ ํค์ ์ ์ ์ id๊ฐ ์กด์ฌํ๋์ง ํ์ธํ๊ณ ์ถ๋ค๋ฉด ์ฝ์์ req.cookies๋ฅผ ์ถ๋ ฅํด๋ณด์ธ์.
*/
};
โฐ console.log(req.cookies)๋ก ํ์ธํ ์ฟ ํค
๐ logout.js
module.exports = (req, res) => {
/*
* TODO: ๋ก๊ทธ์์ ๋ก์ง์ ๊ตฌํํ์ธ์.
*
* cookie-parser์ clearCookie('์ฟ ํค์ ํค', cookieOption) ๋ฉ์๋๋ก ํด๋น ํค๋ฅผ ๊ฐ์ง ์ฟ ํค๋ฅผ ์ญ์ ํ ์ ์์ต๋๋ค.
* ๋ง์ฝ res.clearCookie('user', cookieOption) ์ฝ๋๊ฐ ์คํ๋๋ค๋ฉด `user=....` ์ฟ ํค๊ฐ ์ญ์ ๋ฉ๋๋ค.
* ๋ก๊ทธ์์ ์ฑ๊ณต์ ๋ํ ์ํ ์ฝ๋๋ 205๊ฐ ๋์ด์ผํฉ๋๋ค.
*/
const cookiesOption = {
domain: 'localhost',
path: '/',
httpOnly: true,
sameSite: 'none',
secure: true,
}
res.status(205).clearCookie('cookieId', cookiesOption).send("logout");
// ์ฟ ํค๋ฅผ ์ญ์ ํ ๋๋ rea.clearCookie๋ฅผ ์ฌ์ฉํ๋ค.
};
'CodeStates > Training' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
S3) Unit 7. [์ค์ต] OAuth(๊นํ๋ธ) ์ฌ์ฉํด์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ (0) | 2023.03.09 |
---|---|
S3) Unit 7. [์ค์ต] Token & Cookie ์ฌ์ฉํด์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ (0) | 2023.03.09 |
S3) Unit 4. [์ค์ต] CMarket Redux (0) | 2023.02.27 |
S3) Unit 4. [์ค์ต] CMarket Hooks (2) | 2023.02.24 |
S3) Unit 3. [์ค์ต] Styled Component ๋ก UI ๊ตฌํํ๊ธฐ (0) | 2023.02.21 |