【问题标题】:Twitter authentication with Passport middleware in Node在 Node 中使用 Passport 中间件进行 Twitter 身份验证
【发布时间】:2012-10-04 18:56:55
【问题描述】:

我正在使用 Node.js(使用 Express 框架)开发一个网站。为了使用 Twitter 身份验证,我使用了 passport 模块 (http://passportjs.org),他的 Twitter 包装器称为 passport-twitter

我的服务器端脚本是:

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , passport = require('passport')
  , keys = require('./oauth/keys')
  , TwitterStrategy = require("passport-twitter").Strategy;

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('foo'));
  app.use(express.session());
  // Initialize Passport!  Also use passport.session() middleware, to support
  // persistent login sessions (recommended).
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(require('less-middleware')({ src: __dirname + '/public' }));
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

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

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

passport.use(new TwitterStrategy({
    consumerKey: keys.twitterConsumerKey,
    consumerSecret: keys.twitterConsumerSecret,
    callbackURL: "http://local.host:3000/auth/twitter/callback"
  },
  function(token, tokenSecret, profile, done) {
    User.findOrCreate({ twitterId: profile.id }, function (err, user) {
      if (err) { return done(err); }
      else { return done(null, user); }
    });
  }
));

app.get('/', routes.index);
app.get('/contacts', routes.contacts);
app.get('/cv', routes.cv);
app.get('/projects', routes.projects);
app.get('/users', user.list);

// Redirect the user to Twitter for authentication.
// When complete, Twitter will redirect the user back to the
// application at /auth/twitter/callback
app.get('/auth/twitter', passport.authenticate('twitter'));

// Twitter will redirect the user to this URL after approval.  Finish the
// authentication process by attempting to obtain an access token.  If
// access was granted, the user will be logged in.  Otherwise,
// authentication has failed.
app.get('/auth/twitter/callback', 
  passport.authenticate('twitter',
    {
      successRedirect: '/',
      failureRedirect: '/login'
    }
  )
);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

登录关联的URI是http://local.host:3000/auth/twitter;当我访问它时,Twitter 向我显示了将我的帐户与我自己的网站链接的身份验证表单,但在此步骤之后,出现以下错误:

Express
500 ReferenceError: User is not defined

我该如何解决这个问题? 最好的问候,维。

【问题讨论】:

  • var 用户而不是 var 用户?

标签: node.js twitter oauth express passport-twitter


【解决方案1】:

进一步解释 Max 的回答:“您需要自己创建 User

Read Here

TL:DR - 基本上你必须有一个用于设置用户和验证用户的用户模式,它需要一个 mongoose 数据库后端,这实际上很容易配置。

基本上是创建这个中间件:

var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

// define the schema for our user model
var userSchema = mongoose.Schema({

    local            : {
        email        : String,
        password     : String,
        group        : String,
    },
    facebook         : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    },
    twitter          : {
        id           : String,
        token        : String,
        displayName  : String,
        username     : String
    },
    google           : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    }

});

// methods ======================
// generating a hash
userSchema.methods.generateHash = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

// checking if password is valid
userSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.local.password);
};

// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);

【讨论】:

    【解决方案2】:

    我认为 api 还没有为不需要用户数据库集成的情况做好准备。我的解决方案是忽略done() 函数并重定向到成功页面。

    passport.use(new TwitterStrategy({
        consumerKey: keys.twitterConsumerKey,
        consumerSecret: keys.twitterConsumerSecret,
        callbackURL: "http://local.host:3000/auth/twitter/callback"
      },
      function(token, tokenSecret, profile, done) {
        //done(null, profile);
        this.redirect('/auth/success');
      }
    ));
    

    【讨论】:

      【解决方案3】:

      在 Kraken 中集成 Passport 的 BeatsMusic OAuth2 策略时遇到了同样的问题。看起来各种 Kraken Passport 集成策略的示例使用了相同的简单示例文档,没有明确讨论用户对象(可以理解)。

      我发现(通过挖掘通过 @https://github.com/krakenjs/kraken-examples/tree/master/with.passport 找到的护照策略示例)用户旨在成为基于 Mongoose 模型架构的模型,并且还配置了 https://github.com/drudge/mongoose-findorcreate 插件。

      在我包含User = require('../PATH_TO/user') 并将这个插件添加到用户模型之后,瞧!没有更多错误:)

      听起来您不需要数据库功能,因此您可能会很好地删除身份验证检查。

      希望这对遇到类似问题的其他人有所帮助。

      【讨论】:

        【解决方案4】:

        当我遇到同样的错误时,我就是这样做的:User 未定义:

        passport.use(new TwitterStrategy({
            consumerKey: keys.twitterConsumerKey,
            consumerSecret: keys.twitterConsumerSecret,
            callbackURL: "http://local.host:3000/auth/twitter/callback"
          },
          function(token, tokenSecret, profile, done) {
            done(null, profile);
          }
        ));
        

        【讨论】:

        • 请不要这样做,这不安全。您有一个 User 实例,在您网站的所有访问者之间共享。这将导致许多安全和访问控制问题。
        • 但我的应用程序说 User 未定义。我必须手动定义它。顺便说一句,我已经更新了我的答案
        • 对,User 是你需要自己实现的东西。它通常是由诸如 Mongoose 之类的 ORM 提供的类或模型。重要的是应用程序的每个用户都应该有一个唯一的实例。
        • 好吧,基本上我的应用程序只需要用户名和照片,所以他们只需登录,Passport 会生成一个 cookie,只要它们连接我就可以读取......我不需要需要一个数据库。在所有的例子中,没有互联网,他们似乎在使用这个虚幻的User 变量,并且没有说明它来自哪里。
        【解决方案5】:

        您必须在某处定义您的用户类型。看起来您希望这个东西 User 存在并具有 findOrCreatefindById 的功能,但您从未在任何地方定义过。您在哪里“找到”这些用户?那些没有被发现的,它们在哪里被“创造”?你在使用数据库吗?你如何连接到数据库?我认为您忘记了“模型”步骤。您可能想看看Mongoose Auth,它类似于 Passport,但它直接插入 Mongoose,它连接到 Mongo 数据库

        【讨论】:

        • 对不起,我犯了一个非常愚蠢的错误!非常感谢您的回答!
        • 为什么在登录用户时需要任何数据库?这不是“必须”。我没有在我的应用程序中使用任何数据库,我没有什么可保存的..
        • vsync 你是对的,你不需要数据库。只有当您想将用户信息从一个请求持久化到另一个请求时,您才需要某种数据库(可以是文件、内存或适当的数据库)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-06
        • 2016-07-19
        • 1970-01-01
        • 2021-12-04
        • 2022-07-11
        • 2019-01-31
        • 1970-01-01
        相关资源
        最近更新 更多