[게시판 만들기] TIL 6. JWT, Logout
clearCookie
JWT 토큰 검증 (
jwt.verify()
)
😀 Notice Board 레파지토리😀
Stack : Javascript, express, nodejs, sequelize
★ : 이번 과정을 통해서 새로 만들어진 파일
☆ : 이번 과정을 통해서 수정된 파일
/
├── 📁/server
│ ├── 📄README.md # Notice_Board README.md 파일
│ ├── 📄index.js # node.js로 작성된 웹 서버 진입점
│ ├── 📄package.json
│ ├── 📄package-lock.json
│ ├── 📄.gitignore # node_modules, env 등 포함되지 않게 설정요망
│ ├── 📁/config # 환경변수
│ │ ├── 📄config.js
│ │ └── 📄jwt.js # jwt 관련 환경변수
│ ├── 📁/controllers # 기능 API
│ │ ├── 📄index.js
│ │ ├── 📁User # 유저관련 API
│ │ ├── 📄☆ index.js
│ │ ├── 📄join.js # join API
│ │ ├── 📄login.js # login API
│ │ └── 📄★ logout.js # logout API
│ ├── 📁/middlewares
│ │ ├── 📄CheckEmailForm.js # email 양식이 맞는지 확인하는 middleware
│ │ ├── 📄CheckPassword.js # password 조건이 맞는지 확인하는 middleware
│ │ └── 📄★ checkToken.js # ★ JWT 검증 middleware
│ ├── 📁/migrations
│ │ ├── 📄20210819052749-create-users.js
│ │ └── 📄20210819065842-add-column-in-usersTable.js
│ ├── 📁/models # DB 모델 파일
│ │ ├── 📄index.js
│ │ └── 📄users.js
│ ├── 📁/routes
│ └── 📄☆ index.js # 분기 파일
│
/controllers/Users/logout.js
const { Users } = require('../../models');
module.exports = {
post : async (req, res) =>{
res.clearCookie("sid");
res.status(205).send("logged out success");
}
}
/middlewares/checkToken.js
const jwt = require('jsonwebtoken');
let secretObj = require("../config/jwt");
const checkToken = (req, res, next) => {
const cookie = req.headers.cookie;
const secret = secretObj.secret;
if (!cookie){
res.status(401).json({
success:false,
message:'unvaild token'
})
}
const token = cookie.split("=")[1];
const check = new Promise((resolve, reject) =>{
jwt.verify(token, secret, (err, decoded) => {
if (err) reject(err);
resolve(decoded);
})
})
check.then(user => {
req.user = user;
next();
}).catch(err => {
res.status(401).json({
success: false,
message: err
})
})
}
module.exports = checkToken;
/routes/index.js
const express = require('express');
const router = express.Router();
const checkToken = require('../middlewares/checkToken');
const { userController, myPageController } = require('../controllers');
router.get('/', (req, res) => {
res.send("Site access success");
});
router.post('/user/join', userController.join.post);
router.post('/user/login', userController.login.post);
router.use(checkToken);
router.post('/user/logout', userController.logout.post);
module.exports = router;
1. controllers
/controllers/Users/logout.js
const { Users } = require('../../models');
module.exports = {
post : async (req, res) =>{
res.clearCookie("sid");
res.status(205).send("logged out success");
}
}
cookieparser 또한 bodyparser와 더불어서 Express 내부에 빌트인 되어있기 때문에 모듈 사용 없이 res.cookie()
와 res.clearCookie()
를 사용할 수 있다. 어제 token을 cookie에 넣어주었기 때문에, 로그아웃이 이 기록을 없애야 한다. 때문에 지정한 쿠키를 clearCookie()
를 이용했다. token을 지울 목적이기 때문에 어제 token이 들어갈 쿠키이름인 “sid”를 매개변수로 하였다.
2. JWT 토큰 검증
/middlewares/checkToken.js
const jwt = require('jsonwebtoken');
let secretObj = require("../config/jwt");
const checkToken = (req, res, next) => {
const cookie = req.headers.cookie;
const secret = secretObj.secret;
if (!cookie){
res.status(401).json({
success:false,
message:'unvaild token'
})
}
const token = cookie.split("=")[1];
const check = new Promise((resolve, reject) =>{
jwt.verify(token, secret, (err, decoded) => {
if (err) reject(err);
resolve(decoded);
})
})
check.then(user => {
req.user = user;
next();
}).catch(err => {
res.status(401).json({
success: false,
message: err
})
})
}
module.exports = checkToken;
jwt.verify()
라는 함수를 사용해 검증한다. verify
함수는 인자로는 발급받은 token, 생성할 때 사용한 비밀키, [옵션]이 된다. 옵션은 있어도 그만, 없어도 그만이다. 검증하면 토큰의 구역 중 PayLoad가 Decoded된다. 이 프로젝트에서는 로그인된 user의 email 값을 불러온다.
check.then(user => {
req.user = user;
next();
}).catch(err => {
res.status(401).json({
success: false,
message: err
})
})
비밀키가 맞아 토큰검증에 성공하면 email이 req.user
저장된다. 앞으로 이것이 중요한 역할을 하게 될 것이다. (req.user = user;
)비밀키가 틀리거나, 만료 시간이 지나면 err가 발생해 catch로 넘어간다.
/routes/index.js
const express = require('express');
const router = express.Router();
const checkToken = require('../middlewares/checkToken');
const { userController, myPageController } = require('../controllers');
router.get('/', (req, res) => {
res.send("Site access success");
});
router.post('/user/join', userController.join.post);
router.post('/user/login', userController.login.post);
router.use(checkToken);
router.post('/user/logout', userController.logout.post);
module.exports = router;
이제 이것을 적용하려면 토큰 인증을 미들웨어처럼 불러오고, router.use()
의 인자로 넣어주면 된다. ( app.use()
처럼) 그리고 이것은 인증이 필요한 라우터 위에 위치해야 한다. 그러므로 앞으로 라우터는 router.use(checkToken);
를 기준으로 그 위에 작성된 라우터는 로그인하지 않아도 되는 기능(인증이 필요 없는 기능), 그 아래에 작성된 라우터는 로그인을 해야 하는 기능(인증이 필요한 기능)이 될 것이다.