REST API 是否根据 header 中的 Passport JWT 令牌更改用户?
REST API is not changing users according to Passport JWT Token in header?
所以我有一个用 Node.JS、MongoDB 和 Express 编写的 REST API。我正在使用护照和 passport-jwt 来使用 JSON 网络令牌进行身份验证,但是当我对不同的用户帐户使用不同的令牌时,请求每次都会保存同一个用户。
这是我在 routes.js 中的身份验证端点:
// 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.' });
}
});
}
});
});
因此,如果用户凭据在数据库中匹配,它会创建一个新令牌并 returns 它。然后我将该令牌放入此端点的 header 中:
// GET user
apiRoutes.get('/users', passport.authenticate('jwt', { session: false }), function(req, res) {
res.json(req.user);
});
我每次都可以对新用户进行身份验证,每次都获得不同的令牌,但 /users 端点总是 returns 同一用户。其他一切都在 API 中工作,注册新用户时数据库正在更新,其他东西正在返回,但即使使用不同的令牌,同一用户也会从护照中返回。我知道我将 header 以正确的方式放在 Postman 中,密钥为 Authorization ,令牌的值前面有 JWT,但我不明白为什么会这样。
如果重要的话,这是我的 passport.js:
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);
}
});
}));
};
有什么想法吗?
所以我发现它显示了用户文档中的第一个条目,因为 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.' });
}
});
}
});
});
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);
}
});
}));
};
Payload在5.5.4版本jwt.sign之后有更多数据,现在_id是payload下_doc的一部分。
由于"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);
}
});
}));
};
所以我有一个用 Node.JS、MongoDB 和 Express 编写的 REST API。我正在使用护照和 passport-jwt 来使用 JSON 网络令牌进行身份验证,但是当我对不同的用户帐户使用不同的令牌时,请求每次都会保存同一个用户。
这是我在 routes.js 中的身份验证端点:
// 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.' });
}
});
}
});
});
因此,如果用户凭据在数据库中匹配,它会创建一个新令牌并 returns 它。然后我将该令牌放入此端点的 header 中:
// GET user
apiRoutes.get('/users', passport.authenticate('jwt', { session: false }), function(req, res) {
res.json(req.user);
});
我每次都可以对新用户进行身份验证,每次都获得不同的令牌,但 /users 端点总是 returns 同一用户。其他一切都在 API 中工作,注册新用户时数据库正在更新,其他东西正在返回,但即使使用不同的令牌,同一用户也会从护照中返回。我知道我将 header 以正确的方式放在 Postman 中,密钥为 Authorization ,令牌的值前面有 JWT,但我不明白为什么会这样。
如果重要的话,这是我的 passport.js:
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);
}
});
}));
};
有什么想法吗?
所以我发现它显示了用户文档中的第一个条目,因为 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.' });
}
});
}
});
});
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);
}
});
}));
};
Payload在5.5.4版本jwt.sign之后有更多数据,现在_id是payload下_doc的一部分。
由于"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);
}
});
}));
};