【问题标题】:passport.js passport.initialize() middleware not in usepassport.js passport.initialize() 中间件未使用
【发布时间】:2013-05-22 18:56:47
【问题描述】:

我正在将 node 与 express + mongoose 一起使用,并尝试将 passport.js 与 restful api 一起使用。
身份验证成功后我不断收到此异常(我在浏览器上看到回调 url):

/Users/naorye/dev/naorye/myproj/node_modules/mongoose/lib/utils.js:419
        throw err;
              ^
Error: passport.initialize() middleware not in use
    at IncomingMessage.req.login.req.logIn (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/http/request.js:30:30)
    at Context.module.exports.delegate.success (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/middleware/authenticate.js:194:13)
    at Context.actions.success (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/context/http/actions.js:21:25)
    at verified (/Users/naorye/dev/naorye/myproj/node_modules/passport-facebook/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth2.js:133:18)
    at Promise.module.exports.passport.use.GitHubStrategy.clientID (/Users/naorye/dev/naorye/myproj/config/passport.js:91:24)
    at Promise.onResolve (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
    at Promise.EventEmitter.emit (events.js:96:17)
    at Promise.emit (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
    at Promise.fulfill (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20)
    at /Users/naorye/dev/naorye/myproj/node_modules/mongoose/lib/query.js:1822:13

我读到我应该把app.use(passport.initialize());app.use(passport.session()); 放在app.use(app.router); 之前,这就是我所做的。这是我注册中间件的 express.js:

var express = require('express'),
    mongoStore = require('connect-mongo')(express),
    flash = require('connect-flash'),
    helpers = require('view-helpers');

module.exports = function (app, config, passport) {
    app.set('showStackError', true);
    // should be placed before express.static
    app.use(express.compress({
        filter: function (req, res) {
            return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
        },
        level: 9
    }));
    app.use(express.favicon());
    app.use(express.static(config.root + '/public'));

    app.use(express.logger('dev'));

    // set views path, template engine and default layout
    app.set('views', config.root + '/app/views');
    app.set('view engine', 'jade');

    app.configure(function () {
        // use passport session
        app.use(passport.initialize());
        app.use(passport.session());

        // dynamic helpers
        app.use(helpers(config.app.name));

        // cookieParser should be above session
        app.use(express.cookieParser());

        // bodyParser should be above methodOverride
        app.use(express.bodyParser());
        app.use(express.methodOverride());

        // express/mongo session storage
        app.use(express.session({
            secret: 'linkit',
            store: new mongoStore({
                url: config.db,
                collection : 'sessions'
            })
        }));

        // connect flash for flash messages
        app.use(flash());

        // routes should be at the last
        app.use(app.router);

        // assume "not found" in the error msgs
        // is a 404. this is somewhat silly, but
        // valid, you can do whatever you like, set
        // properties, use instanceof etc.
        app.use(function(err, req, res, next){
            // treat as 404
            if (~err.message.indexOf('not found')) {
                return next();
            }

            // log it
            console.error(err.stack);

            // error page
            res.status(500).render('500', { error: err.stack });
        });

        // assume 404 since no middleware responded
        app.use(function(req, res, next){
            res.status(404).render('404', {
                url: req.originalUrl,
                error: 'Not found'
            });
        });
    });
};

怎么了?

更新 根据@Peter Lyons,我已将配置顺序更改为以下,但我仍然遇到相同的错误:

var express = require('express'),
    mongoStore = require('connect-mongo')(express),
    flash = require('connect-flash'),
    helpers = require('view-helpers');

module.exports = function (app, config, passport) {
    app.set('showStackError', true);
    // should be placed before express.static
    app.use(express.compress({
        filter: function (req, res) {
            return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
        },
        level: 9
    }));
    app.use(express.favicon());
    app.use(express.static(config.root + '/public'));

    app.use(express.logger('dev'));

    // set views path, template engine and default layout
    app.set('views', config.root + '/app/views');
    app.set('view engine', 'jade');

    app.configure(function () {

        // dynamic helpers
        app.use(helpers(config.app.name));

        // cookieParser should be above session
        app.use(express.cookieParser());

        // bodyParser should be above methodOverride
        app.use(express.bodyParser());
        app.use(express.methodOverride());

        // express/mongo session storage
        app.use(express.session({
            secret: 'linkit',
            store: new mongoStore({
                url: config.db,
                collection : 'sessions'
            })
        }));

        // connect flash for flash messages
        app.use(flash());

        // use passport session
        app.use(passport.initialize());
        app.use(passport.session());

        // routes should be at the last
        app.use(app.router);

        // assume "not found" in the error msgs
        // is a 404. this is somewhat silly, but
        // valid, you can do whatever you like, set
        // properties, use instanceof etc.
        app.use(function(err, req, res, next){
            // treat as 404
            if (~err.message.indexOf('not found')) {
                return next();
            }

            // log it
            console.error(err.stack);

            // error page
            res.status(500).render('500', { error: err.stack });
        });

        // assume 404 since no middleware responded
        app.use(function(req, res, next){
            res.status(404).render('404', {
                url: req.originalUrl,
                error: 'Not found'
            });
        });
    });
};

【问题讨论】:

标签: node.js express mongoose restful-authentication passport.js


【解决方案1】:

按照示例来避免无序的中间件地狱,因为 express 使得它很容易进入。直接来自文档。请注意您的与此不完全匹配。

var app = express();
app.use(require('serve-static')(__dirname + '/../../public'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

文档

  1. cookie 解析器
  2. 会话
  3. passport.initialize
  4. passport.session
  5. app.router

  1. passport.initialize
  2. passport.session
  3. cookie 解析器
  4. 会话
  5. app.router

【讨论】:

  • 我已将其更改为您的建议,但仍然会引发此错误。我用新的 express.js 文件更新了我的问题/
  • 所以你这里的代码不是你的顶级代码。在您的程序的早期,您是否拨打过app.getapp.post 等电话?这些将导致路由器比您预期的更早添加到堆栈中。从调用express() 函数获取app 对象开始,向我们展示所有相关代码。这是我的第二个猜测。
  • 我注意到 app.use(app.router);在护照初始化后调用,但我调用: require('./config/routes')(app, passport, auth);在调用表达配置之前。在两条线之间切换解决了这个问题。谢谢!
  • 这对我有用!但是为什么中间件必须这样排列呢?
  • 通过设计,您可以依赖已完成的先决条件。如果 cookieParser 尚未解析 cookie,则会话将不起作用。
【解决方案2】:

在我的情况下(相同的错误消息)我完全忘记添加护照初始化:

app.configure(function () {
    ...
    app.use(passport.initialize());
    app.use(passport.session());
});

更新:仅适用于 express 版本 3,版本 4 不再支持 app.configure()

【讨论】:

【解决方案3】:

Peter Lyons 的回答帮助我解决了这个问题,但我以不同的方式解决了它。

app.use(
  cookieSession({
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: [keys.cookieKey],
  }),
);
app.use(passport.initialize());
app.use(passport.session());

查看我的GitHub repo 了解整个代码,而不仅仅是这里的代码 sn-p。

【讨论】:

    【解决方案4】:

    在我的情况下,错误是因为我试图承诺 req.login 而不将 this 绑定到 req,所以当调用该函数时它找不到 passport 设置。 如果您使用的是 Node v8,解决方案是先绑定 req.login.bind(req),然后再将其传递给 promisify

    【讨论】:

    • 这个“范围问题”发生了,例如当您使用 function({ login }) 之类的参数解构时,将 req 作为第一个参数传递。您的解决方案对我有用,谢谢
    • 是的,这就是 this 在 Javascript 中的工作方式。如果您不将该函数作为对象方法调用,则this 将是undefined(或浏览器中的window
    • 提示任何阅读此答案但不理解它的人...如果您调查Function.prototype.callFunction.prototype.applythis 如何在 Javascript 中工作以及原型继承背后的原则,您将提升到进程中的Javascript Guru级别:)
    • 干杯,我希望它会像 util.promisify(req.login.bind(req)); 一样简单
    【解决方案5】:

    对我有帮助的还有将 routes 放在 cookies 配置之后:

    // init Cookies:
    app.use(
        cookieSession({
            maxAge: 30 * 24 * 60 * 60 * 1000,
            keys: [keys.cookieKey]
        })
    );
    app.use(passport.initialize());
    app.use(passport.session());
    
    // init routes
    const authRoutes = require("./routes/authRoutes")(app);
    

    【讨论】:

    • 知道为什么配置工作后初始化路由会起作用吗?
    • 这解决了我的问题。我移动了所有的路线。在任何与护照相关的事情之后使用电话。
    【解决方案6】:

    就我而言(同样的错误消息),我正在开发一个自定义策略,并且我不需要使用会话。我只是忘记在我的路由 authenticate 中间件中添加 session: false

      app.post('/api/public/auth/google-token',
        passport.authenticate('google-token', {
          session: false
        }),
        function (req: any, res) {
          res.send("hello");
        }
      );
    

    【讨论】:

      【解决方案7】:

      app.use(passport.initialize()) 中间件放在app.router 中间件前面,它的作用就像一个魅力

      【讨论】:

        【解决方案8】:

        您所要做的就是将此代码放在您使用的路由器之前

        app.use('/users', usersRouter);//this is the router  I am using
        
        //and this is the code you have to copy
        
        app.use(passport.initialize());
        app.use(passport.session());
        
        

        【讨论】:

          猜你喜欢
          • 2021-08-25
          • 2019-12-26
          • 2018-08-25
          • 2019-01-26
          • 2018-07-04
          • 2016-01-01
          • 1970-01-01
          • 2019-10-28
          • 2018-06-23
          相关资源
          最近更新 更多