passport.js passport.initialize () проміжне програмне забезпечення не використовується


103

Я використовую вузол Express + мангуста і намагаюся використовувати passport.js з спокійними 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'
            });
        });
    });
};

Версії Express 4.x не підтримують деякі методи. Дивіться github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Відповіді:


206

Слідкуйте за прикладом, щоб уникнути пекла проміжного програмного забезпечення, який не вийшов із ладу, який виражає полегшення введення. Прямо з док. Зверніть увагу, як ваш точно не відповідає цьому.

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. cookieParser
  2. сесія
  3. passport.initialize
  4. паспорт.сесія
  5. app.router

ти

  1. passport.initialize
  2. паспорт.сесія
  3. cookieParser
  4. сесія
  5. app.router

Я змінив це на те, що ви пропонуєте, але це все ще кидає цю помилку. Я оновив своє запитання новим файлом express.js /
Naor

7
Тож код, який у вас є тут, не є вашим кодом вищого рівня. Раніше в вашій програмі ви робите будь-які виклики app.get, app.postі т.д.? Це призведе до того, що маршрутизатор буде доданий в стек раніше, ніж ви плануєте. Покажіть нам ВСІ коду розкриття, починаючи з того часу, коли ви викликаєте express()функцію отримання appоб'єкта. Це моя друга здогадка.
Пітер Ліонс

3
Я помітив, що app.use (app.router); викликається після ініціалізації паспорта, але я дзвоню: вимагаю ('./ config / route') (додаток, паспорт, auth); перед викликом висловити конфігурації. Перемикання між обома лініями вирішило проблему. Дякую!
Наор

1
Це працювало для мене! Але чому проміжне програмне забезпечення повинно бути таким, щоб це було?
Ентоні

3
Створюючи дизайн, ви можете розраховувати на необхідні умови. Сесія не працюватиме, якщо cookieParser ще не розібрав файли cookie.
Пітер Ліонс

12

У моєму випадку (те саме повідомлення про помилку) я взагалі забув додати ініціалізацію паспорта:

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

ОНОВЛЕННЯ: Тільки опрацьовуючи версію 3, версія 4 вже не підтримує app.configure ()


1
App.configure більше не можна використовувати. github.com/strongloop/express/wiki/… .. Вони повинні оновити документи паспорта. правильно?
jack blank

9

У моєму випадку помилка , тому що я намагався promisify req.loginбез прив'язки thisдо req, тому , коли функція була викликана вона не може знайти passportнастройки. Рішення є обов'язковим req.login.bind(req)до передачі, promisifyякщо ви використовуєте Node v8.


І ця "проблема сфери" трапляється, наприклад, коли ви використовуєте аргументи руйнування, як function({ login })передача reqяк перший аргумент. Ваше рішення спрацювало на мене, дякую
Мануель Ді Іоріо

Так, це thisпрацює в Javascript. Якщо ви не будете називати функцію об’єктним методом, тоді thisце буде undefined(або windowв браузері)
Jiayi Hu

Порада для тих, хто читає цю відповідь і не розуміє її ... якщо ви досліджуєте Function.prototype.call, Function.prototype.applyяк thisпрацює Javascript та принципи, що лежать в основі прототипічного успадкування, ви просунетеся до рівня Гуру Javascript у процесі :)
Stijn de Witt

Ура, я сподівався, що це буде так просто, якutil.promisify(req.login.bind(req));
Х. Лам

4

Що мені також допомогло, це встановити маршрути ПІСЛЯ налаштування файлів cookie :

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

У вас є ідея, чому це маршрутизація init після конфігурації працює?
Ішу

Це вирішило мою проблему. Я перемістив усі маршрути. Користуйтеся дзвінками після того, як було пов'язано паспорт.
Нік Ван Брунт

2

Відповідь Пітера Лайона допомогла мені вирішити це, але я вирішив це по-різному.

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

Подивіться на мій репортаж GitHub на весь код, а не лише фрагмент коду тут.


1

У моєму випадку (те саме повідомлення про помилку) я розробляв власну стратегію і мені не потрібно використовувати сеанс . Я просто забув додати session: falseв свій маршрут authenticateпроміжне програмне забезпечення.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.