์ธ์
์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์ฑ๊ณตํ ์ํ
์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ(Session-based authentication)
์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์ฑ๊ณตํ ์ํ๋ฅผ ์๋ฒ์ ์ ์ฅํด์ ๊ด๋ฆฌํ๋ ๋ฐฉ์
์ค์ต
์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ ํ๋ฆ์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํด ํ์ธํด๋ณด๋ ์ค์ต์ด๋ค.
์์ฑํ ํ์ผ์ ๋ค์๊ณผ ๊ฐ๋ค.
์์ฑํ ํ์ผ์ index.html, style.css, login.js, server.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>๋ก๊ทธ์ธ ์ค์ต</h1>
<form>
<label for="user_id">์์ด๋</label>
<input autocomplete="false" id="user_id" />
<label for="user_password">๋น๋ฐ๋ฒํธ</label>
<input id="user_password" type="password" />
<button id="login_button">๋ก๊ทธ์ธ</button>
</form>
<main>
<div>์ ์ ์ด๋ฆ : <span id="user_name"></span></div>
<div>์ ์ ์ ๋ณด : <span id="user_info"></span></div>
<button id="logout_button">๋ก๊ทธ์์</button>
</main>
<!-- axios cdn -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="login.js"></script>
</body>
</html>
style.css
body {
padding: 0 20px;
}
label {
display: inline-block;
width: 80px;
text-align: center;
}
form {
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto;
gap: 8px;
justify-content: start;
}
#login_button {
grid-column: 3 / 4;
grid-row: 1 / 3;
width: 80px;
}
main {
border: 1px solid gray;
border-radius: 10px;
padding: 20px;
margin-top: 20px;
width: 300px;
display: none;
}
div {
margin-bottom: 20px;
}
#logout_button {
width: 100%;
height: 50px;
}
terminal
npm init -y #์๋ก์ด package.json ํ์ผ ๋ง๋ค๊ธฐ, ๋ชจ๋ ์ด๊ธฐ ์ธํ
npm i express cors cookie-parser express-session
#express, cors, cookie-parser, express-session ์ค์น
*express-session : express์์์ ์ธ์ ๊ด๋ฆฌ์ฉ ๋ฏธ๋ค์จ์ด
์ธ์ ์ ์ฟ ํค๋ก ์ ์ฅํ๊ธฐ
server.js
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const users = [
{
user_id: 'test',
user_password: '1234',
user_name: 'ํ
์คํธ์ ์ ',
user_info: '์ ๋ ํ
์คํธ์ ์ ์
๋๋ค...',
},
];
const app = express();
app.use(
cors({
origin: ['http://127.0.0.1:5500', 'http://localhost:5500'],
methods: ['POST', 'GET', 'DELETE', 'OPTIONS'],
credentials: true, // ์ฟ ํค ์ ์ฅ์ ์ํด ํ์
}),
);
app.use(cookieParser());
app.use(express.json());
app.use(
session({
// ์ํธํ๋ฅผ ์ํด ์ค์ ํ๋ ๋น๋ฐ ์ฝ๋
secret: 'session secret',
resave: false, // request๊ฐ ๋ ๋๋ง๋ค ์ธ์
๋ฐ์ดํฐ๋ฅผ ํญ์ ๋ค์ ์ ์ฅํ ์ง ์ฌ๋ถ (๋ณ๊ฒฝ์ด ์์ด๋)
// ์ด๊ธฐํ๋์ง ์์ ์ธ์
์ ์ ์ฅํ ์ง ์ฌ๋ถ (์ธ์
์ ์๋ฌด ๋ด์ฉ์ด ์์ด๋ ์ ์ฅํ ์ง)
saveUninitialized: false,
name: 'session_id',
}),
);
// ๋ ๋๋ง
app.post('/', (req, res) => {
console.log(req.body);
});
app.listen(3000, () => console.log('์๋ฒ ์คํ'));
login.js
// ์ฌ๊ธฐ์ ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ์์ฑํ์ธ์.
const form = document.querySelector('form');
const idInput = document.querySelector('#user_id');
const passwordInput = document.querySelector('#user_password');
const loginBtn = document.querySelector('#login_button');
// ์ฟ ํค ๊ด๋ฆฌ๋ฅผ ์ํด์ ํ์
axios.defaults.withCredentials = true;
// ํผ ์ ์ก ์ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉด์ ์๋ฒ๋ก ์ ์ก๋๋ ๋์์ ๋ง๋ ์ญํ
form.addEventListener('submit', (e) => e.preventDefault());
function login() {
const userId = idInput.value;
const userPassword = passwordInput.value;
return axios.post('http://localhost:3000', { userId, userPassword });
}
loginBtn.onclick = login;
์ผ๋จ ์ด๋ ๊ฒํ๋ฉด ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ ์ ๋ login.js์์ ์ ์กํ request์ body๋ฅผ ์ฝ์์ ์ถ๋ ฅํด id์ password๋ฅผ ์ฝ์๋ก ํ์ธํด๋ณผ ์ ์๋ค.
์ฌ๊ธฐ์ ์ด์ ์ฟ ํค๋ก ์ ์ฅํ๋ ค๋ฉด server.js์ ๋ ๋๋ง ๋ถ๋ถ์ ๋ฐ์์จ req.body๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ธ์ ์ ์ ์ฅํด ์ ๋ฌํด์ฃผ๋ฉด ๋๋ค.
// ๋ผ์ฐํ
app.post('/', (req, res) => {
const { userId, userPassword } = req.body;
// ๋ก๊ทธ์ธ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ userInfo์ ๋ด์
const userInfo = users.find(
(el) => el.user_id === userId && el.user_password === userPassword,
);
if (!userInfo) {
res.status(401).send('๋ก๊ทธ์ธ ์คํจ');
} else {
// ์ฟ ํค๋ฅผ ๋ฐ๋ก ์ ๋ฌํ ํ์ ์์ด express-session์์ ์์์ ๋ค ํด์ค...
req.session.userId = userInfo.user_id;
res.send('์ธ์
์์ฑ ์๋ฃ');
}
});
์ด์ ์๋ ์ฟ ํค๋ฅผ ๋ณด๋ผ ๋ res.cookie('test-cookie', 'my cookie'); ์ด๋ฐ์์ผ๋ก ๋ณด๋ด๊ณค ํ๋๋ฐ, ์ด๋ express-session์์ ๊ธฐ๋ณธ ์ค์ ์ ๋ค ์ฒ๋ฆฌํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ํด์ค ํ์๊ฐ ์์ด์ก๋ค!
์ฟ ํค ๊ฐ์ ธ์ค๊ธฐ
login.js
function getUserInfo() {
return axios.get('http://localhost:3000');
}
loginBtn.onclick = () => {
login().then(() => getUserInfo());
};
์ด์ ์ฟ ํค ์ ๋ณด๋ฅผ ์์ฒญํด ์ธ์ id๋ฅผ ํ์ธํด ์ผ์นํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ ๋ฐ๋๋ก get ์์ฒญ์ ์ถ๊ฐํ๋ค.
server.js
app.get('/', (req, res) => {
console.log(req.session);
});
์ผ๋จ์ ์ง๊ธ req.session์ผ๋ก ์ธ์ ๊ฐ์ด ์ด๋ป๊ฒ ๋ค์ด์ค๊ณ ์๋์ง ํ์ธํด๋ณด๋ฉด
๋ญ๊ฐ ๊ฐ์ด ๋ค์ด์ค๊ณ ๋ ์๋๋ฐ.... ์ ์ ๊ฐ์ ธ์ค๊ณ ์ถ์ ์์ด๋ ๊ฐ์ด ์๋ณด์ธ๋ค...
์๋ํ๋ฉด ์ง๊ธ live server ์ต์คํ ์ ์ผ๋ก ๊ตฌ๋์ค์ด๋ผ ์ฃผ์ ๊ฐ์ด http://127.0.0.1:5500/~~์ธ ์ํ์ธ๋ฐ,
์ง๊ธ ๋ค์ด์จ ์ฟ ํค๋ฅผ ํ์ธํด๋ณด๋ฉด
Domain์ด localhost์์ ์ ์ ์๋ค.
๋ฌผ๋ก ์ ๊ธ์์ ์ธ๊ธํ๋ฏ์ด http://127.0.0.1:5500/~~๋ http://localhost:5500/ ๋ ๊ฒฐ๊ณผ์ ์ผ๋ก๋ ๊ฐ์ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค์ง๋ง,
๋๋ฉ์ธ ์ผ์น ๋ฌธ์ ๋ก ์ฟ ํค ๊ณต์ ๊ฐ ์ง๊ธ์ฒ๋ผ ๊นจ์ง ์ ์๋ค.
๋๋ฌธ์ ๊ธฐ์กด ์ฃผ์์ 127.0.0.1์ localhost๋ก ๋ฐ๊ฟ์ ์ค์ตํด๋ณด๋ ๊ฒ์ด ์ข๋ค.....
์ด์ ๋๋ฉ์ธ๊ณผ ์ฃผ์๊ฐ ์ผ์นํ๊ณ
console.log(req.session)์์๋ ์ด์ userId๊ฐ์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค!
์ด์ ๊ฐ์ด ์ ๋ค์ด์ค๋ ๊ฒ์ ํ์ธํ์ผ๋ ๋ธ๋ผ์ฐ์ ์์๋ ๋ฐ์์จ ๊ฐ์ ๋ ๋๋งํ๋ ค๊ณ ํ๋ค.
server.js
app.get('/', (req, res) => {
const userInfo = users.find((el) => el.user_id === req.session.userId);
return res.json(userInfo);
});
login.js
// ๊ธฐ์กด html์์ ์๊ฐ์ ธ์จ ์์๋ค์ ์ถ๊ฐ๋ก ๊ฐ์ ธ์ด
const main = document.querySelector('main')
const userName = document.querySelector('#user_name')
const userInfo = document.querySelector('#user_info')
const logoutButton = document.querySelector('#logout_button')
// ์๋ต...
// ๋ ๋๋ง ๊ธฐ๋ฅ
function renderUserInfo(user) {
main.style.display = 'block';
form.style.display = 'none';
userName.textContent = user.user_name;
userInfo.textContent = user.user_info;
}
loginBtn.onclick = () => {
login()
.then(() => getUserInfo())
.then((res) => renderUserInfo(res.data));
};
๋ก๊ทธ์์ ๊ธฐ๋ฅ
server.js
app.delete('/', (req, res) => {
// ์ธ์
์ ์ ๋ณด๋ฅผ ์์ ์ฃผ๋ ๋ฉ์๋
req.session.destroy();
// ์ฟ ํค๋ ์ญ์ ํด์ฃผ๊ธฐ
res.clearCookie('session_id');
res.send('์ธ์
์ญ์ ์๋ฃ');
});
login.js
function logout() {
return axios.delete('http://localhost:3000');
}
// ๋ก๊ทธ์์ ํ ๋ค์ ์ด๊ธฐ ๋ก๊ทธ์ธ ํผ์ ๋์์ฃผ๋ ํจ์
function renderLoginForm() {
main.style.display = 'none';
form.style.display = 'grid';
userName.textContent = '';
userInfo.textContent = '';
}
logoutBtn.onclick = () => {
logout().then((res) => {
console.log(res);
renderLoginForm();
});
};
'Node.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Node.js / ํ ํฐ(Token) (0) | 2025.05.15 |
---|---|
Node.js / ์ฟ ํค(Cookie) (0) | 2025.05.14 |
Node.js / ๋คํธ์ํฌ ๊ธฐ์ด (0) | 2025.05.12 |