웹페이지에서 로그인을 오래동안 유지하다보면 다음과 같은 창이 나오기도 한다.
이는 로그인(인증)을 한 지 오래되어 서버에서 로그인을 만료시키기에 일어나는 일이다.
유저가 웹페이지에 회원가입하고 로그인을 하여 자신이 회원임을 인증함으로써, 웹페이지는 해당 유저에게 웹페에지의 기능을 사용할 수 있는 권한을 인가하게된다.
그런데 만약 한번 로그인을 하면 영원이 지속되도록 한다면, 유저의 권한이 침해당할 수 있다.
상태를 말하며, 여기서는 로그인이 되어있는 상태를 말한다.
로그인 세션이 없다면 한 기능을 사용할려고 접근할 때마다 로그인을 해야하는 번거로움이 생기게 된다.
JWT홈페이지에서 인코딩(암호화)된 데이터를 디코딩(번역) 해준걸 볼 수 있다.

다음과 같이 디코딩된 형태가 JSON형태이기에 jwt라고 부른다.
alg: 암호화에 사용된 알고리즘tpy: 말그대로 타임jsonwebtoken라이브러리를 사용하여 구현하고자 한다.
설치
$ npm install jsonwebtoken
토큰 만들기
var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');
// token 생성 = jwt 서명을 했다! (페이로드, 나만의 암호키) + 기본적으로 제공되는 HS256로 암호화가 진행됨
console.log(token);
[Running] node "jwt-demo.js"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE3NDA5MDQ3OTB9.OzH9x71f4DRG-XgoFI3aw-9JQ-Ez1heVZB0MAipH6Ww

검증하기
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded) // bar
[Running] node "jwt-demo.js"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE3NDA5MDUwMDR9.FwfEXNQXv2JCaK0H64_ilztNnl_d5-Xn1vutH79slDk
{ foo: 'bar', iat: 1740905004 }

iat?
시간을 나타내는 것으로, JWT토큰이 언제 발행되었는지 알려준다.
또한, 각 시간마다 토큰의 이름이 달라지는 것을 알 수 있다.
변수로 관리
const privateKey = 'shhhh';
var token = jwt.sign({ foo: 'bar' },privateKey);
외부 파일(.txt)로 관리
// sign with RSA SHA256
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey);
.env로 관리
환경 변수 설정값을 넣어서 만드는 파일로,
등등의 외부에 유출되면 안되는 중요한 환경 변수들을 따로 관리하기 위한 파일확장자
dotenv 라이브러리를 통해 관리할 수 있다.
설치
npm i dotenv
.env파일 생성 후 내용 추가
PRIVATE_KEY = "shhhh" # JWT 암호키
코드 수정
var jwt = require('jsonwebtoken');
var dotenv = require('dotenv');
// .env파일 사용하겠다는 선언
dotenv.config();
var token = jwt.sign({ foo: 'bar' }, process.env.PRIVATE_KEY);
이전에 했던거 처럼 user파일의 로그인에 JWT를 넣어서 보내주면 된다.
cookie() 명령어를 통해 jwt 토큰을 쿠키에 넣어 보낼 수 있다.
// 로그인
router.post("/login",
[
body('email').notEmpty().isEmail().withMessage('이메일 형식 필요!'),
body('password').notEmpty().isStrongPassword().withMessage('비밀번호 필요!'),
validate
]
,(req, res, next)=>{
try{
isExist(req.body, res);
const {email, password} = req.body;
let selEmailSQL = `SELECT * FROM Users WHERE email = "${email}"`;
db.query(selEmailSQL, function(err, results, fields){
if (err){
console.log(err);
return res.status(400).end();
};
let userInfo = results[0];
if (userInfo && userInfo.password === password){
// token 발급
const token = jwt.sign({
emila: userInfo.email,
name: userInfo.name
}, process.env.PRIVATE_KEY);
res.cookie("token", token)
console.log("로그인에 성공하였습니다.");
res.status(200).json({
message: `${userInfo.name}님 환영합니다.`,
});
} else {
console.log(err);
res.status(403).json({message: "아이디 또는 비밀번호가 틀렸습니다."});
};
});
// 메인 페이지로 이동
} catch {
res.status(500).json({message: "서버와의 연결에 실패하였습니다."})
}
})
지금까지 JWT를 쿠키에 담아서 클라이언트에게 보내는 거 까지했다.
근데 지금은 유효기간을 설정하지 않았기에 유효기간 설정하는 것을 할것이다.
const token = jwt.sign({
emila: userInfo.email,
name: userInfo.name
}, process.env.PRIVATE_KEY,{
expiresIn : '5m',
issuer: "root"
});

Secure
쿠키에서 Secure라는게 있다. 이는 보안과 관련된 것인데, HTTP로 보내는지 HTTPS 보내는지에 따라 false, true로 나뉘어진다.
HttpOnly
API호출만 허락하는지를 true, false로 선택할 수 있는 창이다.
true라면 화면을 신경쓰지 말고 HTTP로 API를 신청했을 때이다.
그래서 이를 true로 설정한다.
res.cookie("token", token, {
httpOnly: true
})
HTTP랑 HTTPS차이
- HTTP (Hypertext Transfer Protocol)
데이터를 암호화 없이 전송하여 보안에 취약함
기본 포트: 80
중간자 공격(MITM)이나 패킷 스니핑에 노출될 수 있음- HTTPS (HTTP Secure)
SSL/TLS 프로토콜을 통해 데이터를 암호화하여 전송
기본 포트: 443
서버 인증서를 통해 신뢰성을 확보하며, 데이터 무결성과 보안을 보장함