User.findOrCreate 函数是做啥的,啥时候在护照中调用它?

Posted

技术标签:

【中文标题】User.findOrCreate 函数是做啥的,啥时候在护照中调用它?【英文标题】:What is function User.findOrCreate doing and when is it called in passport?User.findOrCreate 函数是做什么的,什么时候在护照中调用它? 【发布时间】:2013-12-24 05:25:58 【问题描述】:

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

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? 
       );

  
));

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

【问题讨论】:

【参考方案1】:

User.findOrCreate 是一个虚构的函数,表示您必须通过 Facebook ID 查找用户的任何函数,或者如果用户不存在则创建一个函数。我认为您的第一个问题是您的回调 URL 只是进入您的根目录,因此您可能永远无法访问该函数。

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

然后处理那个 URL:

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

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

您在该函数中执行的操作取决于您。所以,制作你自己的User.findOrCreate。这是 Facebook 护照中的代码,其中包含一些 cmets 来解释它。这假设您使用的是 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);
            
        );
    
));

就我个人而言,我还使用“会员”表来跟踪每个用户的多个帐户(因此他们可以使用多个帐户进行身份验证),因为我通过 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);

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

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

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

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

【讨论】:

我正在尝试为我完成这项工作,但事实并非如此。你说得对,我从不调用我的回调函数。你能告诉我为什么这个函数在你的情况下 Membership.findOne(.. 需要在代码中?我试图把它放在没有,但它似乎永远不会终止。 @Tommz 在代码中将配置文件信息保存到数据库中。在最简单的形式中,您可以尝试在 function(accessToken... 中返回 return done(null, profile);,因为它需要返回一些东西,否则,就像你说的,它似乎永远不会终止。 是的,但是当我有这样的代码并收到此错误时,当我想这样做时会出现问题:***.com/questions/20436387/…。另外,我已经尝试在函数(accessToken... > @MikeSmithDev 这可能是一个愚蠢的问题,但是您是否确定同一用户是否已经通过电子邮件与另一个社交提供者注册(所以只有当提供者为社交帐户返回相同的电子邮件地址时你知道它和你数据库中的那个是一样的吗? @MaximZubarev 是的,这确实是我所做的。如果没有找到具有提供者 ID 的人,那么接下来检查电子邮件以确保您没有为现有成员创建另一个帐户。上面的代码中没有包含它,但会在 if (!user) 部分中。【参考方案2】:

如果您想使用findOrCreate,请尝试使用npm 包mongoose-findorcreate,或supergoose

例如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);
        );
    
));

【讨论】:

以上是关于User.findOrCreate 函数是做啥的,啥时候在护照中调用它?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中action函数是做啥的

这个宏定义是做啥的?

mfc中的settimer函数是做啥的里面的参数呢

glStencilMask() 到底是做啥的? [复制]

我是 python 新手,我偶然发现了一个函数/变量?我不知道它是做啥的,有人可以解释一下吗? [复制]

app.use(cors()) 是做啥的?