在 mongodb 中将多个 passportjs 提供程序保存到同一个用户文档中
Saving multiple passportjs providers into same user document in mongodb
我遇到了无法解决的问题。我正在使用 nodejs 开发一个应用程序,使用 mongodb、expressjs 和 passportjs 作为我的身份验证中间件。
我目前有3个策略:facebook、twitter和instagram。我想要实现的是,当用户第一次登录时,如果用户使用一种策略登录并使用另一种策略登录,则将配置文件保存到同一个 mongodb 用户文档中。
这是我的 auth/index.js:
require('./local/passport').setup(User, config);
require('./facebook/passport').setup(User, config);
require('./twitter/passport').setup(User, config);
require('./instagram/passport').setup(User, config);
var router = express.Router();
router.use('/local', require('./local'));
router.use('/facebook', require('./facebook'));
router.use('/twitter', require('./twitter'));
router.use('/instagram', require('./instagram'));
例如,这是我的 auth/twitter/index.js
var router = express.Router();
router
.get('/', passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}))
.get('/callback', passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}), auth.setTokenCookie);
module.exports = router;
但是我如何将 mongodb _id 传递给此 auth/twitter/passport.js 以便将其传递给猫鼬查询并更新用户?像制作 POST 到 auth/twitter 并访问 req.user._id 之类的东西?我不知道该怎么做。
exports.setup = function (User, config) {
var passport = require('passport');
var TwitterStrategy = require('passport-twitter').Strategy;
var TwitterApi = require('twitter');
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: config.twitter.callbackURL
},
function(token, tokenSecret, profile, done) {
User.findOne({
'twitter.id_str': profile.id
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
user = new User({
role: 'user',
[...]
非常感谢。
编辑:
这就是我设置 cookie 的方式:
function setTokenCookie(req, res) {
if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'});
var token = signToken(req.user._id, req.user.role);
res.cookie('token', JSON.stringify(token));
res.redirect('/');
}
和 signToken 函数:
function signToken(id) {
return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*24*30 });
}
为什么 req.user 和 req.session 在我的策略中总是空的?
编辑2:
我想我可以在调用策略之前使用 auth.isAuthenticated() 函数将用户附加到请求。我所做的是:
router
.get('/', auth.isAuthenticated(), passport.authenticate('twitter', auth.isAuthenticated, {
failureRedirect: '/',
session: false
}))
.get('/callback', auth.isAuthenticated(), passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}), auth.setTokenCookie);
但现在我遇到了这个问题:
UnauthorizedError: No Authorization header was found
我对 auth/twitter 的请求来自 $window.location。似乎这并没有将用户对象附加到请求,因为当我使用 isAuthenticated() 进行 GET 或 POST 时,用户对象被正确传递。这是我的 isAuthenticated() 函数:
function isAuthenticated() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// allow access_token to be passed through query parameter as well
if(req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
User.findById(req.user._id, function (err, user) {
if (err) return next(err);
if (!user) return res.send(401);
req.user = user;
next();
});
});
}
您可以在定义通行证策略时将passReqToCallback
设置为true
。它将发出当前请求,因此当前登录的用户可用于您的回调函数。
exports.setup = function (User, config) {
var passport = require('passport');
var TwitterStrategy = require('passport-twitter').Strategy;
var TwitterApi = require('twitter');
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: config.twitter.callbackURL,
passReqToCallback: true
},
function(req, token, tokenSecret, profile, done) {
User.findOne({
'twitter.id_str': profile.id
}, function(err, user) {
if (err) return done(err);
if (!user) {
if (req.user) {
[...]
仅供参考,我刚刚在我的策略中处理了解码 JWT 令牌的问题。我不知道这是否是一个好的做法,但问题是如果请求是用 $window.location.href 发出的,我没有让我的用户附加到请求
所以在我的策略中,我读取 cookie 并即时解码它以在数据库中搜索用户。
谢谢。
我遇到了无法解决的问题。我正在使用 nodejs 开发一个应用程序,使用 mongodb、expressjs 和 passportjs 作为我的身份验证中间件。
我目前有3个策略:facebook、twitter和instagram。我想要实现的是,当用户第一次登录时,如果用户使用一种策略登录并使用另一种策略登录,则将配置文件保存到同一个 mongodb 用户文档中。
这是我的 auth/index.js:
require('./local/passport').setup(User, config);
require('./facebook/passport').setup(User, config);
require('./twitter/passport').setup(User, config);
require('./instagram/passport').setup(User, config);
var router = express.Router();
router.use('/local', require('./local'));
router.use('/facebook', require('./facebook'));
router.use('/twitter', require('./twitter'));
router.use('/instagram', require('./instagram'));
例如,这是我的 auth/twitter/index.js
var router = express.Router();
router
.get('/', passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}))
.get('/callback', passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}), auth.setTokenCookie);
module.exports = router;
但是我如何将 mongodb _id 传递给此 auth/twitter/passport.js 以便将其传递给猫鼬查询并更新用户?像制作 POST 到 auth/twitter 并访问 req.user._id 之类的东西?我不知道该怎么做。
exports.setup = function (User, config) {
var passport = require('passport');
var TwitterStrategy = require('passport-twitter').Strategy;
var TwitterApi = require('twitter');
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: config.twitter.callbackURL
},
function(token, tokenSecret, profile, done) {
User.findOne({
'twitter.id_str': profile.id
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
user = new User({
role: 'user',
[...]
非常感谢。
编辑: 这就是我设置 cookie 的方式:
function setTokenCookie(req, res) {
if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'});
var token = signToken(req.user._id, req.user.role);
res.cookie('token', JSON.stringify(token));
res.redirect('/');
}
和 signToken 函数:
function signToken(id) {
return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*24*30 });
}
为什么 req.user 和 req.session 在我的策略中总是空的?
编辑2:
我想我可以在调用策略之前使用 auth.isAuthenticated() 函数将用户附加到请求。我所做的是:
router
.get('/', auth.isAuthenticated(), passport.authenticate('twitter', auth.isAuthenticated, {
failureRedirect: '/',
session: false
}))
.get('/callback', auth.isAuthenticated(), passport.authenticate('twitter', {
failureRedirect: '/',
session: false
}), auth.setTokenCookie);
但现在我遇到了这个问题:
UnauthorizedError: No Authorization header was found
我对 auth/twitter 的请求来自 $window.location。似乎这并没有将用户对象附加到请求,因为当我使用 isAuthenticated() 进行 GET 或 POST 时,用户对象被正确传递。这是我的 isAuthenticated() 函数:
function isAuthenticated() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// allow access_token to be passed through query parameter as well
if(req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
User.findById(req.user._id, function (err, user) {
if (err) return next(err);
if (!user) return res.send(401);
req.user = user;
next();
});
});
}
您可以在定义通行证策略时将passReqToCallback
设置为true
。它将发出当前请求,因此当前登录的用户可用于您的回调函数。
exports.setup = function (User, config) {
var passport = require('passport');
var TwitterStrategy = require('passport-twitter').Strategy;
var TwitterApi = require('twitter');
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: config.twitter.callbackURL,
passReqToCallback: true
},
function(req, token, tokenSecret, profile, done) {
User.findOne({
'twitter.id_str': profile.id
}, function(err, user) {
if (err) return done(err);
if (!user) {
if (req.user) {
[...]
仅供参考,我刚刚在我的策略中处理了解码 JWT 令牌的问题。我不知道这是否是一个好的做法,但问题是如果请求是用 $window.location.href 发出的,我没有让我的用户附加到请求 所以在我的策略中,我读取 cookie 并即时解码它以在数据库中搜索用户。
谢谢。