加密Nodejs JWT令牌

时间:2020-04-03 02:16:40

标签: node.js express jwt express-jwt passport-jwt

我一直在遵循从article创建测试API应用程序的教程。在本文的结尾,我提到了最好加密jwt令牌以提高安全性,因此我也寻求一种方法来做到这一点。我遇到了这个article,它提供了有关如何使用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
    });
  });
});

1 个答案:

答案 0 :(得分:1)

我没有时间复制它。您的登录部分似乎正确。但是,您应该尝试设置这种受保护的路由,并根据您的第一篇文章进行复制并量身定制:

设置中间件以处理jwt解密,如果在单独的文件中进行设置,请确保在NewsFeedDataItem.sharedBy或您需要的任何地方要求它。以后可以在控制器中将其用作中间件:

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());以便我可以将请求正文作为json发送-如果您更喜欢使用urlencoded

  • ,则无需这样做
  • 问题在于您导出的app.js是另一台路由器,并且您尝试将其用作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
  });
});
  • 第三件事是不要忘记在调用API时将令牌添加到查询参数中,例如... 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 }); };

您应该得到答复:

http://localhost:3000/user?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjVlODc2Yjc1YTVlNTk3MTRlOGFjMmI4NyIsImVtYWlsIjoiYUBiLmNvbSJ9LCJpYXQiOjE1ODU5MzMyNjR9.lcLuQeCMRy7Ef9zNkIt_rn4S22t2cm7YLRE7Jgp1Mpw