使用 MongoDB Atlas 和 Passport.js 设置 Facebook 身份验证

Setting Up Facebook Authentication with MongoDB Atlas and Passport.js

我做了很多研究来找到我的问题的答案,但我还没有发现任何东西。如果我错过了答案,请随时附上 link。

我确实找到了这个解决方案,但我不确定它如何适用于这种情况:E11000 duplicate key error index in mongodb mongoose

我正在尝试将我的 Express.js、MongoDB、Passport.js 应用程序连接到 Mongo-Atlas。我设置了 Atlas 集群并从我的本地主机接受新用户并使用 Google Oauth 2.0,但是,当我尝试使用 Facebook 注册或登录时,出现以下错误。

MongoError: E11000 duplicate key error collection: userDB.users index: username_1 dup key: { username: null } 

会不会跟这个有关?

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

它在连接到我的本地主机 MongoDB 时有效,正如我所说,我在寻找解决方案时遇到了麻烦。

passport.use(new FacebookStrategy({
    clientID: process.env.FBAPPID,
    clientSecret: process.env.FBSECRET,
    callbackURL: "http://localhost:3000/auth/facebook/secrets"
  },
  function(accessToken, refreshToken, profile, cb) {
    console.log(profile);
    User.findOrCreate({ facebookId: profile.id }, function (err, user) {
      return cb(err, user);
    });
  }
));

app.get('/auth/facebook', passport.authenticate('facebook'));

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

更新

所以我找到了一些关于在 MongoDB However that wasn't entirely clear, so I also found an article Dropping Existing Indexes 上删除索引的文档,所以我将代码实现到我自己的 app.js 文件中。

// Dropping an Index in MongoDB
User.collection.dropIndex({name : "username_1"}, function(err, res) {
    if (err) {
        console.log('Error in dropping index!', err);
    }
});

我一直在测试之间删除数据库以查看它是否有效,但是无论我如何更改代码以尝试修复它,我都会抛出这个错误!

{ _bsontype: 'Timestamp', low_: 1, high_: 1586408833 },
  ok: 0,
  errmsg: `can't find index with key: { name: "username_1" }`,
  code: 27,
  codeName: 'IndexNotFound',
  '$clusterTime': {
    clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1586408833 },
    signature: { hash: [Binary], keyId: [Long] }
  },
  name: 'MongoError',
  [Symbol(mongoErrorContextSymbol)]: {}
}

然而,当我 运行 db.users.getIndexes() 在我的 Mongo Shell 中连接到我的 Atlas 服务器时。果然在那里!我什至尝试使用 dropIndexes,但它只删除了电子邮件索引!我对此感到非常沮丧!

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "userDB.users"
    },
    {
        "v" : 2,
        "key" : {
            "email" : 1
        },
        "name" : "email_1",
        "ns" : "userDB.users",
        "background" : true
    },
    {
        "v" : 2,
        "unique" : true,
        "key" : {
            "username" : 1
        },
        "name" : "username_1",
        "ns" : "userDB.users",
        "background" : true
    }
]

您在用户名上定义了一个唯一索引,但您的代码没有插入用户名(可能是因为用户名没有像您期望的那样从身份验证提供程序中检索到)。这会导致多个文档在用户名字段 (null) 中具有相同的值。

如果您的用户应该有用户名,您需要调试您的代码以弄清楚为什么它不检索用户名或将其传递给 MongoDB。如果用户名是可选的,请删除其上的唯一索引。

终于点击了!我进入了 Atlas 的索引选项卡并删除了所需的用户名索引。谢谢你的帮助@oleg 出于某种原因我在网上找不到这个解释!

更新

所以从Mongo-Atlas中删除索引只是暂时解决了问题。我相信我想出了如何从我的代码中删除索引,但我已经从 Mongo shell 中删除了它,这似乎也解决了问题。所以我将提供两个命令:

const User = new mongoose.model('User', userSchema);

User.collection.indexExists({ "username" : 1 }, function(err, results){
  console.log(results);
  if ( results === true) {
    // Dropping an Index in MongoDB
    User.collection.dropIndex( { "username" : 1 } , function(err, res) {
        if (err) {
            console.log('Error in dropping index!', err);
        }
    });
  } else {
    console.log("Index doesn't exisit!");
  }
});

在 Mongo Shell 中,进入您的数据库并 运行 此命令:

db.users.dropIndex( { "username" : 1 } );

确认,运行:

db.users.getIndexes() 

为了解决这个问题花了很多时间研究!希望对你有帮助!

转到您的 atlas 集群,然后打开集合,然后打开索引

然后手动删除 username_1 索引。

db.users.dropIndex( { "username" : 1 } );

这是有效的!!!