728x90
안녕하세요 이번 시간에는 JWT, JSON Web Token 에 대해서 알아보겠습니다.
JWT 란?
JWT는 JSON 객체를 사용하여 정보를 안전하게 전달하기 위한 코딩된 토큰입니다. 주로 웹에서 사용자 인증에 사용되며, 서버와 클라이언트 간에 정보를 안전하게 전송하기 위한 수단으로 활용됩니다.
Express.js와 ejs 를 사용하여 JWT를 생성, 검증 및 디코드하는 간단한 프로젝트를 만드는 방법을 알아보겠습니다.
먼저 구현을 위해 필요한 패키지 설치를 합니다
npm install express jsonwebtoken body-parser ejs
프로젝트 구조는 다음과 같습니다
/jwt-express-test
|-- /views
| |-- index.ejs
|-- app.js
app.js
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
const path = require('path');
const secretKey = 'your_secret_key';
const algorithm = 'HS256';
// 바디 파서를 사용하여 JSON 요청을 처리합니다.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// EJS 템플릿 엔진을 사용하도록 설정합니다.
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// 토큰에서 "Bearer " 문자열을 제거하여 순수한 토큰 문자열을 추출합니다.
const extractToken = (headerValue) => {
if (headerValue && headerValue.startsWith('Bearer ')) {
return headerValue.slice(7);
}
return null;
};
// JWT의 내용을 디코딩하여 확인합니다.
app.get('/decode', (req, res) => {
const token = extractToken(req.headers.authorization);
if (!token) {
return res.status(401).json({ message: 'Token not provided.' });
}
const decodedPayload = jwt.decode(token);
if (!decodedPayload) {
return res.status(401).json({ message: 'Invalid token.' });
}
res.json(decodedPayload);
});
// JWT의 유효성을 검증합니다.
app.get('/verify', (req, res) => {
const token = extractToken(req.headers.authorization);
if (!token) {
return res.status(401).json({ message: 'Token not provided.' });
}
jwt.verify(token, secretKey, { algorithms: [algorithm] }, (err, decoded) => {
if (err) {
return res.status(401).json({ message: 'Invalid token.' });
}
res.json({ message: 'Token is valid.', user: decoded.user });
});
});
// 사용자에게 JWT를 발급합니다.
app.get('/token', (req, res) => {
const payload = {
user: 'user_id',
role: 'admin'
};
const token = jwt.sign(payload, secretKey, { expiresIn: '1h', algorithm });
res.json({ token });
});
// 루트 경로에 EJS 템플릿을 렌더링합니다.
app.get('/', (req, res) => {
res.render('index');
});
app.listen(3000, () => {
console.log('Server started on http://localhost:3000');
});
EJS 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>JWT Test</title>
</head>
<body>
<h2>JWT Test Page</h2>
<button id="getToken">Get Token</button>
<p><strong>Token:</strong> <span id="token"></span></p>
<h3>Verify Token:</h3>
<textarea id="inputToken" rows="3" style="width: 100%"></textarea>
<!-- 토큰 입력 부분 -->
<button id="verifyToken">Verify Token</button>
<p>
<strong>Verification Result:</strong>
<span id="verificationResult"></span>
</p>
<button id="decodeToken">Decode Token</button>
<p><strong>Decoded Info:</strong> <span id="decoded"></span></p>
<script>
// 타임스탬프를 'YYYY-MM-DD HH:mm:ss' 형식의 날짜 문자열로 변환합니다.
function convertToDateTime(timestamp) {
const date = new Date(timestamp * 1000);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// 토큰을 받아옵니다.
document
.getElementById("getToken")
.addEventListener("click", async () => {
const response = await fetch("/token");
const data = await response.json();
document.getElementById("token").textContent = data.token;
});
// 입력된 토큰의 유효성을 검증합니다.
document
.getElementById("verifyToken")
.addEventListener("click", async () => {
const token = document.getElementById("inputToken").value;
const response = await fetch("/verify", {
headers: {
Authorization: "Bearer " + token,
},
});
const data = await response.json();
if (data.message && data.message === "Invalid token.") {
alert("올바르지 않은 토큰입니다."); // 팝업으로 메시지 표시
}
document.getElementById("verificationResult").textContent =
data.message || JSON.stringify(data, null, 2);
});
// 받아온 토큰의 내용을 디코드합니다.
document
.getElementById("decodeToken")
.addEventListener("click", async () => {
const token = document.getElementById("token").textContent;
const response = await fetch("/decode", {
headers: {
Authorization: "Bearer " + token,
},
});
const data = await response.json();
if (data.iat) {
//발행시간
data.iat = convertToDateTime(data.iat);
}
if (data.exp) {
//만료시간
data.exp = convertToDateTime(data.exp);
}
document.getElementById("decoded").textContent = JSON.stringify(
data,
null,
2
);
});
</script>
</body>
</html>
시연 영상입니다
[참고자료]
https://en.wikipedia.org/wiki/JSON_Web_Token
'Nodejs' 카테고리의 다른 글
[Node.js] dotenv을 사용하여 환경변수 설정하기 (0) | 2023.10.19 |
---|---|
[Node.js] axios 활용해서 비동기로 http 통신하기 (0) | 2023.10.08 |
[Nodejs] CORS 사용해서 특정 도메인만 접근 허용하기 (0) | 2023.09.29 |
[Node.js]Multer를 이용한 다중 이미지 업로드 (0) | 2023.09.24 |
[Nodejs]Node.js에서 i18n을 사용하여 다국어 지원 하기 (0) | 2023.09.14 |