JWT(JSON Web Token)는 사용자 인증방법 중의 하나로서 토큰의 종류와 해시 알고리즘 정보가 있는 헤더, 토큰의 인코딩 부분인 페이로드, 암호화된 문자열을 통해 토큰의 변조 여부를 확인하는 시그니처 세 부분으로 구성되어 있는 정보값을 의미합니다. 이 정보(토큰)를 사용자에게 부여하고 해당 토큰의 확인을 통해 사용자를 인증합니다.
참고로 아래 사이트에서 JWT토큰의 구조와 정보 값을 확인할 수 있습니다.
이번 포스팅에서는 JWT를 이용해 사용자의 로그인과정을 거치는 간단한 예제를 만들어 보고자 합니다.
JWT는 아래 방법으로 설치할 수 있습니다.
npm i jwt |
JWP설 설치하고 나면 .env 파일에 임의의 키값을 저장해 둡니다. 이 키값은 외부에 노출되어서는 안 됩니다.
JWT_SECRET=키값 |
다음으로 JWT토큰을 확인하여 만료 여부와 유효성을 파악한 다음 디코딩한 정보를 담아두는 미들웨어를 추가합니다. 에제에서는 이 미들웨어를 login디렉터리 안에 userjwt.js 파일명으로 저장하였습니다.
const jwt = require('jsonwebtoken');
require('dotenv').config();
exports.verifyToken = (req, res, next) => {
try
{
req.decoded = jwt.verify(req.cookies.user, process.env.JWT_SECRET);
return next();
}
catch (error) {
if (error.name === 'TokenExpiredError') {
return res.status(419).json({
code: 419,
message: '토큰만료'
});
}
return res.status(401).json({
code: 401,
message: '유효하지 않은 토큰'
});
}
};
예제는 보시면 jwt의 verify() 함수를 통해 토큰과 위에서 설정한 키값을 통해 해당 토큰의 유효성을 확인하고 있습니다. 아무런 문제가 없다면 decoded 안에 토큰을 복호화(디코딩)한 결괏값을 저장할 것입니다.
login 디렉터리 안에 다음과 같은 HTML 파일을 생성합니다. 사실 이번 예제에서는 사용자의 비밀번호 여부는 확인하지 않기 때문에 비밀번호를 입력하는 부분은 필요하지 않습니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="/login/token" method="post">
아이디 : <input type="test" id="id" name="id" /><br />
비밀번호 : <input type="password" id="pw" name="pw" /><br />
<button type="submit">확인</button>
</form>
</body>
</html>
login디렉터리에 index.js 파일을 다음과 같은 내용으로 추가합니다.
const express = require('express');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const { verifyToken } = require('./userjwt');
const router = express.Router();
router.use(express.urlencoded({ extended: true }));
router.use(cookieParser());
router.get('/', (req, res) => {
res.sendFile(`${__dirname}/login.html`);
});
router.post('/token', (req, res) => {
const token = jwt.sign({
id: req.body.id,
name: 'abcdefg'
}, process.env.JWT_SECRET, {
expiresIn: '5m'
});
res.cookie('user', token, {
httpOnly: true
});
res.send('발급됨');
});
router.get('/user', verifyToken, (req, res) => {
res.send(req.decoded);
});
router.get('/test', (req, res) => {
res.send(req.cookies.user);
});
module.exports = router;
토큰은 쿠키에 저장하므로 cookie를 사용할 수 있도록 해야 하며 login으로 라우트를 분리한 상태입니다.
사용자가 /user를 요청하면 위에서 만들어둔 login.html 파일을 응답합니다. login.html에서 로그인을 시도하면 해당 정보를 /login/token으로 보내고 입력한 id값을 받아 JWT토큰을 생성한 뒤 쿠키에 담다 둠으로 서 토큰 발급을 완료합니다.
토큰을 발급할 때는 jwt의 sign() 함수를 사용하며 sign에 토큰으로 들어갈 객체를 설정하고 expiresIn속성에 토큰의 유효시간을 설정합니다. 예제에서는 5m으로 했는데 5분을 의미하며 h를 사용해 시간 단위로 설정할 수도 있습니다.
아후 /login/user를 요청하면 verifyToken 미들웨어를 거쳐 쿠키로 전달되어온 토큰 값이 유효한지 여부를 확인합니다. 아무런 문제가 없으면 decoded안에 결괏값을 답게 되고 사용자에게 req.decoded값을 읽어 표시합니다. 사용자 인증이 필요한 모든 라우트에 이와 같이 verifyToken을 붙여두고 인증절차를 거치면 됩니다.
'Server > node.js' 카테고리의 다른 글
[node.js] WebSocket (0) | 2021.03.09 |
---|---|
[node.js] express-rate-limit(DOS공격 방어하기) (2) | 2021.03.09 |
[node.js] mariaDB CRUD (시퀄라이즈) (0) | 2021.03.08 |
[node.js] Express (0) | 2021.03.05 |
[node.js] 패키지 관리 (0) | 2021.03.04 |