안녕하세요 이번 시간에는 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
JSON Web Token - Wikipedia
From Wikipedia, the free encyclopedia JSON-based standard for passing claims between parties in web application environments JSON Web Token (JWT, pronounced , same as the word "jot"[1]) is a proposed Internet standard for creating data with optional signat
en.wikipedia.org
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
'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 |