node.js User.findOrCreate 函数在做什么以及它何时在护照中调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20431049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:28:02  来源:igfitidea点击:

What is function User.findOrCreate doing and when is it called in passport?

node.jspassport.js

提问by Tommz

I can't find documentation on this function and therefor I can't make it work right. When is that function being called, what is it doing and what is it taking as first parameters? I'm trying to get access token from passport, but can't reach it anyhow.

我找不到有关此功能的文档,因此无法使其正常工作。该函数何时被调用,它在做什么以及它把什么作为第一个参数?我正在尝试从护照获取访问令牌,但无论如何都无法访问它。

passport.use(new FacebookStrategy({
    clientID:   APP_ID,
    clientSecret:   APP_SECRET,
    callbackURL: "http://localhost:3000/",
  },
  function(accessToken, refreshToken, profile, done) {
    User.findOrCreate({// what are these parameters?}, function (err, user) {
        // when is this function called and what is it doing? 
       });

  }
));

How can I get access token from passport?

如何从护照获取访问令牌?

回答by MikeSmithDev

User.findOrCreateis a made-up function that represents whatever function you have to find a user by Facebook ID, or to create one if the user doesn't exist. I think your first problem is that your callback URL is just going to your root, so you probably are never getting to that function.

User.findOrCreate是一个虚构的函数,表示您必须通过 Facebook ID 查找用户或在用户不存在时创建一个用户的任何函数。我认为您的第一个问题是您的回调 URL 只是转到您的根目录,因此您可能永远不会使用该功能。

Your callback URL should be like http://localhost:3000/auth/facebook/callback.

您的回调 URL 应该类似于http://localhost:3000/auth/facebook/callback.

And then handle that URL:

然后处理该 URL:

app.get('/auth/facebook/callback', 
  passport.authenticate('facebook', { failureRedirect: '/login' }),
  function(req, res) {
    res.redirect('/');
  });

At this point Authentication is complete. accessTokenis returned to you -- "this is needed any time the app calls an API to read, modify or write a specific person's Facebook data on their behalf". You should save this off in some table where you store access tokens for a user. profileis the other key variable because that is the info about the user (what info depends on the service).

至此,身份验证完成。accessToken返回给您——“每当应用程序调用 API 来代表他们读取、修改或写入特定人的 Facebook 数据时,都需要这样做”。您应该将其保存在某个表中,您可以在其中存储用户的访问令牌。profile是另一个关键变量,因为这是有关用户的信息(哪些信息取决于服务)。

What you do inside that function is up to you. So, make your own User.findOrCreate. Here is the code from passport for Facebook with some comments to explain it. This assumes you are using something like MongoDB and have a Usertable. Userin this case is whatever variable you declared that can interface with the Usertable.

您在该函数中做什么取决于您。所以,做你自己的User.findOrCreate。这是 Facebook 护照中的代码,并附有一些注释来解释它。这假设您使用的是 MongoDB 之类的东西并有一张User表。User在这种情况下,是您声明的可以与User表交互的任何变量。

//Use facebook strategy
passport.use(new FacebookStrategy({
        clientID: config.facebook.clientID,
        clientSecret: config.facebook.clientSecret,
        callbackURL: config.facebook.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
        //check user table for anyone with a facebook ID of profile.id
        User.findOne({
            'facebook.id': profile.id 
        }, function(err, user) {
            if (err) {
                return done(err);
            }
            //No user was found... so create a new user with values from Facebook (all the profile. stuff)
            if (!user) {
                user = new User({
                    name: profile.displayName,
                    email: profile.emails[0].value,
                    username: profile.username,
                    provider: 'facebook',
                    //now in the future searching on User.findOne({'facebook.id': profile.id } will match because of this next line
                    facebook: profile._json
                });
                user.save(function(err) {
                    if (err) console.log(err);
                    return done(err, user);
                });
            } else {
                //found user. Return
                return done(err, user);
            }
        });
    }
));

Personally I also use a "membership" table to track multiple accounts per user (so they can authenticate with multiple accounts), as I set it up through mongoose. This is actually where I store that access token. I prefer this to having a facebook column in the user table.... but that is up to you.

我个人还使用“成员资格”表来跟踪每个用户的多个帐户(因此他们可以使用多个帐户进行身份验证),因为我是通过 mongoose 设置的。这实际上是我存储访问令牌的地方。我更喜欢在用户表中有一个 facebook 列......但这取决于你。

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

var membershipSchema = new Schema({
    provider:  String,
    providerUserId:  String,
    accessToken: String,
    userId: {type: ObjectId, ref: 'User'},
    dateAdded: {type: Date, default: Date.now}
});

module.exports = mongoose.model('Membership', membershipSchema);

and as such, my version of User.findOrCreatestarts off like this:

因此,我的版本是这样User.findOrCreate开始的:

function(accessToken, refreshToken, profile, done) {
    Membership.findOne({
        providerUserId: profile.id
    }, function(err,membershipData) {
            //blah blah blah

where membership is that model above, and is defined as a variable as:

其中成员资格是上面的模型,并被定义为一个变量:

var Membership =  require('./models/membership.js')

回答by Vinnie James

If you would like to use findOrCreate, try the npm package mongoose-findorcreate, or supergoose

如果您想使用findOrCreate,请尝试使用 npm 包mongoose-findorcreatesupergoose

e.g. mongoose-findorcreate

例如 mongoose-findorcreate

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');

var findOrCreate = require('mongoose-findorcreate')
var Schema = mongoose.Schema;
var UserSchema = new Schema({ facebookId: Number});
UserSchema.plugin(findOrCreate);
var User = mongoose.model('User', UserSchema);

passport.use(new FacebookStrategy({
        clientID: 'clientID',
        clientSecret: 'clientSecret',
        callbackURL: "/auth/facebook/callback"
    },
    function(accessToken, refreshToken, profile, cb) {
        User.findOrCreate({ facebookId: profile.id }, function (err, user) {
          console.log('A new uxer from "%s" was inserted', user.facebookId);
          return cb(err, user);
        });
    }
));