令牌(用于测试)我只让它持续 60 秒,但它似乎永远不会过期。通过 Postman 上的承载,getInfo 路由不断给我一个响应,就好像令牌在 60 秒后仍然有效一样。我可能做错了什么?
我有这个文件夹树:
├── app.js
├── node_modules
├── package-lock.json
├── package.json
├── private
│ ├── private.key
│ └── public.key
├── public
│ ├── html
│ │ └── cover.html
│ └── images
│ ├── logo-w.png
│ └── logo.png
├── request.http
├── src
│ ├── auth
│ │ ├── authService.js
│ │ └── tokenManager.js
│ ├── middleware
│ │ └── authMiddleware.js
│ └── routes
│ ├── auth.js
│ └── info.js
我有不同的文件,但主文件是app.js
const express = require("express");
const path = require("path");
const port = process.env.PORT || 3000;
const app = express();
const fs = require('fs');
const jwt = require('jsonwebtoken');
require('dotenv').config();
app.use(express.static("public"));
app.use(express.json());
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "public/html", "cover.html"));
});
const infoRoute = require("./src/routes/info");
const authRoute = require("./src/routes/auth");
app.use("/info", infoRoute);
app.use("/auth", authRoute);
app.listen(port, () => {
console.log("Server Is Running On Port", port);
});
在我的 authService.js 中,我模拟了一个简单的登录来进行测试:
const { issueJWT, issueRefreshToken } = require('./tokenManager');
const users = [{ id: 1, username: 'test', password: 'password' }];
const login = (username, password) => {
const user = users.find(u => u.username === username && u.password === password);
if (!user) throw new Error('Credentials not valid');
const tokenObject = issueJWT(user);
const refreshToken = issueRefreshToken(user);
return {
...tokenObject,
refreshToken: refreshToken
};
};
module.exports = { login };
在我的 tokenManager.js 中
const jwt = require('jsonwebtoken');
const fs = require('fs');
const path = require('path');
const PRIV_KEY = fs.readFileSync(path.join(__dirname, '../../private/private.key'), 'utf8');
const issueJWT = (user) => {
const expiresIn = 60;
const payload = {
sub: user.id,
iat: Date.now(),
};
const signedToken = jwt.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' });
return {
token: "Bearer " + signedToken,
expires: expiresIn
};
};
const issueRefreshToken = (user) => {
const expiresIn = '7d';
const payload = {
sub: user.id,
iat: Date.now(),
};
const refreshToken = jwt.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' });
return refreshToken;
};
module.exports = { issueJWT, issueRefreshToken };
在我的 authMiddleware.js 中
const jwt = require('jsonwebtoken');
const fs = require('fs');
const path = require('path');
const PUB_KEY = fs.readFileSync(path.join(__dirname, '../../private/public.key'), 'utf8');
const authenticateJWT = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const token = authHeader.split(' ')[1];
jwt.verify(token, PUB_KEY, { algorithms: ['RS256'] }, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
} else {
res.sendStatus(401);
}
};
module.exports = { authenticateJWT };
auth.js
const express = require('express');
const router = express.Router();
const { login } = require('../auth/authService');
const jwt = require('jsonwebtoken');
const { issueJWT } = require('../auth/tokenManager');
const fs = require('fs');
const path = require('path');
const PUB_KEY = fs.readFileSync(path.join(__dirname, '../../private/public.key'), 'utf8');
// Endpoint per il login
router.post('/login', (req, res) => {
const { username, password } = req.body;
try {
const { token, expires, refreshToken } = login(username, password); // Aggiunto refreshToken
res.json({
success: true,
token: token,
expiresIn: expires,
refreshToken: refreshToken // Inviato il refreshToken nella risposta
});
} catch (error) {
res.status(401).json({ success: false, message: error.message });
}
});
// Endpoint per il rinnovo del token
router.post('/refreshToken', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(401).json({ message: "Refresh Token richiesto" });
}
try {
const payload = jwt.verify(refreshToken, PUB_KEY, { algorithms: ['RS256'] });
// Aggiungi qui la logica per verificare che il refresh token sia ancora valido, per esempio controllando nel tuo database
const user = { id: payload.sub }; // Assumi che tu possa ottenere l'utente in base al sub nel payload
const newTokenObject = issueJWT(user);
res.json({
success: true,
token: newTokenObject.token,
expiresIn: newTokenObject.expires
});
} catch (error) {
return res.status(403).json({ message: "Refresh Token non valido" });
}
});
module.exports = router;
最后在我的 info.js (保护区)
const express = require('express');
const router = express.Router();
const { authenticateJWT } = require('../middleware/authMiddleware');
router.get('/getInfo', authenticateJWT, (req, res) => {
res.json({ message: 'Protected area' });
});
module.exports = router;
您需要更改代码中的三个部分。
在
./src/auth/tokenManager.js
const issueJWT = (user) => {
const expiresIn = 60; // 60 seconds
const payload = {
sub: user.id,
iat: Date.now(),
exp: Math.floor(Date.now() / 1000) + expiresIn // exp is in seconds since Unix epoch
};
const signedToken = jwt.sign(payload, PRIV_KEY, { algorithm: 'RS256' });
return {
token: signedToken,
expires: expiresIn
};
};
“承载者”不是 nessaray
来自
token: "Bearer " + signedToken,
至
token: signedToken,
并且
payload.exp
需要从now()开始添加60秒
在
./src/middleware/authMiddleware.js
const authenticateJWT = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const token = authHeader.split(' ')[1];
const decodedToken = jwt.decode(token, { complete: true });
const nowInSeconds = Math.floor(Date.now() / 1000); // Convert current time to seconds
if (decodedToken.payload.exp < nowInSeconds) {
// Token has expired
return res.sendStatus(401);
}
jwt.verify(token, PUB_KEY, { algorithms: ['RS256'] }, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
} else {
res.sendStatus(401);
}
};
'const demodToken = jwt.decode(token, {complete: true });' 可以提取'decodedToken.payload.exp'过期毫秒。所以你必须除以 1000 来换算秒并进行比较。
获取代币URL
POST http://localhost:3000/auth/login
在
Tests
选项卡中
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("test-token", jsonData.token);
console.log(pm.environment.get("test-token"));
体内
{
"username": "test",
"password": "password"
}
获取用户信息
GET http://localhost:3000/info/getInfo
60秒后,调用API