加密 Nodejs JWT 令牌
Encrypt Nodejs JWT Token
我一直在关注从这个 article. At the end of the article i see a mention its best to encrypt the jwt token for added security so i wen searching for a way to do that as well. I ran into this article 创建测试 API 应用程序的教程,它给出了如何使用 RSA private/public 密钥加密 jwt 令牌的示例。
这就是我卡住的地方。在我使用 /signup 路由成功注册后,我可以使用 /login 路由获取我的令牌。所以我假设这是我在将令牌发送回用户之前使用我的私钥加密令牌的地方?
**制作 repo public 用于测试 - 您只需要在 app.js
中提供 mongoDB 连接字符串
我卡在了过程的 encrypt/decrypt 部分,感谢任何帮助。
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);
});
然后在调用 "secure" 路由时,我需要根据 public 密钥解密令牌并 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"
}
}
我一直在关注从这个 article. At the end of the article i see a mention its best to encrypt the jwt token for added security so i wen searching for a way to do that as well. I ran into this article 创建测试 API 应用程序的教程,它给出了如何使用 RSA private/public 密钥加密 jwt 令牌的示例。
这就是我卡住的地方。在我使用 /signup 路由成功注册后,我可以使用 /login 路由获取我的令牌。所以我假设这是我在将令牌发送回用户之前使用我的私钥加密令牌的地方?
**制作 repo public 用于测试 - 您只需要在 app.js
中提供 mongoDB 连接字符串我卡在了过程的 encrypt/decrypt 部分,感谢任何帮助。
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);
});
然后在调用 "secure" 路由时,我需要根据 public 密钥解密令牌并 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"
}
}