REST API不会根据标头中的Passport JWT令牌更改用户?

时间:2016-07-16 23:45:25

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

所以我有一个用Node.JS,MongoDB和Express编写的REST API。我使用passport和passport-jwt使用JSON Web令牌进行身份验证,但是当我为不同的用户帐户使用不同的令牌时,请求每次都会保存同一个用户。

这是我在routes.js中的身份验证端点:

Connection: close

因此,如果用户凭据在数据库中匹配,则会创建一个新令牌并将其返回。然后我将该标记放入此端点的标题中:

// Authenticate the user and get a JSON Web Token to include in the header of future requests.
  apiRoutes.post('/authenticate', function(req, res) {
    User.findOne({
      email: req.body.email
    }, function(err, user) {
      if (err) throw err;

      if (!user) {
        res.send({ success: false, message: 'Authentication failed. User not found.' });
      } else {
        // Check if password matches
        user.comparePassword(req.body.password, function(err, isMatch) {
          if (isMatch && !err) {
            // Create token if the password matched and no error was thrown
            var token = jwt.sign(user, config.secret, {
              //expiresIn: 10080 // in seconds
            });
            res.json({ success: true, token: 'JWT ' + token, _id: user._id });
          } else {
            res.send({ success: false, message: 'Authentication failed. Passwords did not match.' });
          }
        });
      }
    });
  });

我每次都可以对新用户进行身份验证,并且每次都会获得不同的令牌,但/ users端点始终返回相同的用户。其他所有工作都在API中,数据库在注册新用户和其他东西时都会得到更新,但即使使用不同的令牌,也会从护照中返回相同的用户。我知道我在Postman中以正确的方式使用授权的密钥和JWT前面的令牌的价值,但我不明白为什么会发生这种情况。

这是我的passport.js,如果重要的话:

// GET user
  apiRoutes.get('/users', passport.authenticate('jwt', { session: false }), function(req, res) {
    res.json(req.user);
  }); 

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

Mongo使用" _"在文档ID之前。而不是User.findOne({id:jwt_payload.id},你应该有User.findOne({_ id:jwt_payload._id},这应该解决问题。



var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var User = require('../models/user');
var config = require('./main');

// Setup work and export for the JWT passport strategy
module.exports = function(passport) {
  var opts = {};
  opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
  opts.secretOrKey = config.secret;
  passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    User.findOne({_id: jwt_payload._id}, function(err, user) {
      if (err) {
        return done(err, false);
      }
      if (user) {
        done(null, user);
      } else {
        done(null, false);
      }
    });
  }));
};




答案 1 :(得分:0)

所以我发现它显示了用户文档中的第一个条目,因为JWT太大了。所以我更改了身份验证路由,使JWT只使用用户的ID和用户名,如下所示:

apiRoutes.post('/authenticate', function(req, res) {
    User.findOne({
      email: req.body.email
    }, function(err, user) {
      if (err) throw err;

      if (!user) {
        res.send({ success: false, response: 'Authentication failed. User not found.' });
      } else {
        // Check if password matches
        user.comparePassword(req.body.password, function(err, isMatch) {
          if (isMatch && !err) {
            // Create token if the password matched and no error was thrown
            var token = jwt.sign({id: user._id, username: user.username }, config.secret, {
              expiresIn: 10080 // in seconds
            });
            res.json({ success: true, response: 'Authentication succeeded! User found.', token: 'JWT ' + token});
          } else {
            res.send({ success: false, response: 'Authentication failed. Passwords did not match.' });
          }
        });
      }
    });
  });  

答案 2 :(得分:0)

在版本5.5.4中的jwt.sign之后,Payload有更多的数据,现在_id是有效载荷下的_doc的一部分。

As" SamuelDuke"建议上面是正确的,只需更改为jwt_payload._doc._id。 请参阅以下更新的代码。

var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var User = require('../models/user');
var config = require('./main');

// Setup work and export for the JWT passport strategy
module.exports = function(passport) {
  var opts = {};
  opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
  opts.secretOrKey = config.secret;
  passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    User.findOne({_id: jwt_payload._doc._id}, function(err, user) {
      if (err) {
        return done(err, false);
      }
      if (user) {
        done(null, user);
      } else {
        done(null, false);
      }
    });
  }));
};