node.js - 加密 Nodejs JWT 令牌
问题描述
我一直在关注这篇文章中关于创建测试 API 应用程序的教程。在文章的结尾,我看到一个提到最好加密 jwt 令牌以增加安全性,所以我也在寻找一种方法来做到这一点。我遇到了这篇文章,它提供了如何使用 RSA 私钥/公钥加密 jwt 令牌的示例。
这就是我卡住的地方。在我使用 /signup 路由成功注册后,我可以使用 /login 路由获取我的令牌。所以我假设这是我在将令牌发送回用户之前使用我的私钥加密令牌的地方?
**公开repo以供测试 - 您只需在 app.js 中提供 mongoDB 连接字符串
我停留在该过程的加密/解密部分,任何帮助表示赞赏。
router.post("/login", async (req, res, next) => {
passport.authenticate("token", async (err, user, info) => {
try {
if (err || !user) {
const error = new Error("An Error occurred");
return next(error);
}
req.login(user, { session: false }, async error => {
if (error) return next(error);
//We don't want to store the sensitive information such as the
//user password in the token so we pick only the email and id
const body = { _id: user._id, email: user.email };
//Sign the JWT token and populate the payload with the user email and id
const token = jwt.sign({ user: body }, PRIV_KEY, { algorithm: 'RS256' });
//Send back the token to the user
return res.json({ token });
});
} catch (error) {
return next(error);
}
})(req, res, next);
});
然后在调用“安全”路由时,我需要根据verify
公钥解密令牌和它吗?
router.get("/profile", (req, res, next) => {
//We'll just send back the user details and the token
jwt.verify(req.query.token, PUB_KEY, { algorithms: ['RS256'] }, function(err, decoded) {
if (err.name === "TokenExpiredError") {
console.log("Whoops, your token has expired!");
}
if (err.name === "JsonWebTokenError") {
console.log("That JWT is malformed!", err); <------ GET ERROR HERE
}
if (err === null) {
console.log("Your JWT was successfully validated!");
}
// Both should be the same
console.log(decoded);
res.json({
message: "You made it to the secure route",
user: req.user
});
});
});
解决方案
我没有时间重现这个。您的登录部分似乎正确。但是,您应该尝试像这样设置受保护的路由,从您的第一篇文章中复制并根据您的需要进行定制:
设置中间件来处理 jwt 解密,app.js
如果你在一个单独的文件中设置它,请确保在你或任何你需要的地方需要它。这可以稍后在您的控制器中用作中间件:
const JWTstrategy = require('passport-jwt').Strategy;
//We use this to extract the JWT sent by the user
const ExtractJWT = require('passport-jwt').ExtractJwt;
//This verifies that the token sent by the user is valid
passport.use(new JWTstrategy({
//secret we used to sign our JWT
secretOrKey : PUB_KEY,
algorithms: ['HS256'],
//we expect the user to send the token as a query parameter with the name 'token'
jwtFromRequest : ExtractJWT.fromUrlQueryParameter('token')
}, async (token, done) => {
try {
//Pass the user details to the next middleware
return done(null, token.user);
} catch (error) {
done(error);
}
}));
设置受保护的路由,注意不需要手动调用jwt.verify
,中间件处理并填充req.user
:
const express = require('express');
const router = express.Router();
//Let's say the route below is very sensitive and we want only authorized users to have access
//Displays information tailored according to the logged in user
router.get('/profile', passport.authenticate('jwt', { session: false }), (req, res, next) => {
//We'll just send back the user details and the token
res.json({
message : 'You made it to the secure route',
user : req.user,
token : req.query.token
})
});
module.exports = router;
**根据您的评论更新:
我克隆了你的仓库,它对我有用,虽然我改变了一些东西:
我添加
app.use(bodyParser.json());
了,app.js
以便我可以将请求正文作为 json 发送 - 如果您更喜欢 urlencoded,这不是必需的问题是
secureRoute
您导出的是另一个路由器,并且您尝试将其用作控制器app.js
:
...
const secureRoute = require('./routes/secure-routes');
...
app.use('/user', passport.authenticate('jwt', { session: false }), secureRoute);`
*请注意,这将是/user
路线,如果您愿意,/profile
请更改为app.use('/profile', ...)
所以而不是
router.get("/profile", (req, res, next) => {
//We'll just send back the user details and the token
res.json({
message: "You made it to the secure route",
user: req.user,
token: req.query.secret_token
});
});
它应该只是一个控制器功能:
...
module.exports = (req, res, next) => {
//We'll just send back the user details and the token
res.json({
message: 'You made it to the secure route',
user: req.user,
token: req.query.token // note that you don't use secret_token but token as a name
});
};
- 第三件事是不要忘记在查询参数中添加令牌,当您调用 API 时,例如
http://localhost:3000/user?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjVlODc2Yjc1YTVlNTk3MTRlOGFjMmI4NyIsImVtYWlsIjoiYUBiLmNvbSJ9LCJpYXQiOjE1ODU5MzMyNjR9.lcLuQeCMRy7Ef9zNkIt_rn4S22t2cm7YLRE7Jgp1Mpw
你应该得到回应:
{
"message": "You made it to the secure route",
"user": {
"_id": "5e876b75a5e59714e8ac2b87",
"email": "a@b.com"
}
}
推荐阅读
- node.js - 如何从自定义对象设置 Firestore 时间戳?
- azure-devops - 如何在 Azure Devops 模板的条件表达式中使用变量
- javascript - 如何处理重复的firebase应用程序初始化
- c# - 如何在 C# 上使用图像的字节数组
- c++ - 我可以重新分配/覆盖 std::string 吗?
- python - 使用python从网站上抓取表格并尝试获取带有文本的内容的超链接
- python - 数字猜谜游戏的编码问题
- c++ - 带有 Protobuf 序列化的 C++ Hazelcast:字符串不是 UTF-8 格式的
- java - 扩展现有 Mapstruct 接口以添加其他映射方法
- node.js - 不正确的 Node.js 方法调用仍然可以编译