passport.js passport.initialize () oprogramowanie pośredniczące nie jest używane

104

Używam węzła z express + mongoose i próbuję użyć passport.js z restful api.
Ciągle otrzymuję ten wyjątek po pomyślnym uwierzytelnieniu (widzę adres zwrotny w przeglądarce):

/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

Przeczytałem, że powinienem umieścić app.use(passport.initialize());i app.use(passport.session());wcześniej app.use(app.router);i to właśnie zrobiłem. Oto mój express.js, który rejestruje oprogramowanie pośrednie:

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'
            });
        });
    });
};

Co jest nie tak?

AKTUALIZACJA Zgodnie z @Peter Lyons zmieniłem kolejność konfiguracji na następującą, ale nadal pojawia się ten sam błąd:

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'
            });
        });
    });
};
Naor
źródło
Wersje Express 4.x nie obsługują niektórych metod. Zobacz github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Odpowiedzi:

207

Postępuj zgodnie z przykładem, aby uniknąć piekła oprogramowania pośredniczącego nieczynnego w kolejności, które Express sprawia, że ​​tak łatwo jest wejść. Prosto z dokumentacji. Zwróć uwagę, że twój nie pasuje do tego dokładnie.

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

Dokumenty

  1. cookieParser
  2. sesja
  3. paszport.initialize
  4. paszport. sesja
  5. app.router

ty

  1. paszport.initialize
  2. paszport. sesja
  3. cookieParser
  4. sesja
  5. app.router
Peter Lyons
źródło
Zmieniłem to na to, co sugerujesz, ale nadal zgłasza ten błąd. Zaktualizowałem moje pytanie o nowy plik express.js /
Naor
7
Więc kod, który tu masz, nie jest kodem najwyższego poziomu. Wcześniej w programie robisz żadnych wywołań app.get, app.postitp? To spowoduje, że router zostanie dodany do stosu wcześniej, niż zamierzasz. Pokaż nam WSZYSTKO rewelacyjny kod zaczynający się od wywołania express()funkcji w celu uzyskania appobiektu. To moje drugie przypuszczenie.
Peter Lyons,
3
Zauważyłem, że app.use (app.router); jest wywoływana po inicjalizacji paszportu, ale dzwonię: require ('./ config / tours') (app, paszport, auth); przed zadzwonieniem w celu ekspresowej konfiguracji. Przełączanie między obiema liniami rozwiązało problem. Dzięki!
Naor
1
To zadziałało dla mnie! Ale dlaczego oprogramowanie pośredniczące musi być takie uporządkowane?
Anthony do
3
Z założenia, dzięki czemu można polegać na spełnieniu wymagań wstępnych. Sesja nie zadziała, jeśli cookieParser nie przeanalizował jeszcze plików cookie.
Peter Lyons,
12

W moim przypadku (ten sam komunikat o błędzie) w ogóle zapomniałem dodać inicjalizacje paszportu:

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

AKTUALIZACJA: Działa tylko do wersji Express 3, wersja 4 nie obsługuje już app.configure ()

Matthias M.
źródło
1
Nie można już używać App.configure. github.com/strongloop/express/wiki/… .. Powinni zaktualizować dokumenty paszportowe. dobrze?
pusty jack
9

W moim przypadku błędu, ponieważ starałem się promisify req.loginbez wiązania thissię req, więc gdy funkcja została wywołana nie mógł znaleźć passportustawienia. Rozwiązanie jest wiążące req.login.bind(req)przed przekazaniem go do, promisifyjeśli używasz Node v8.

Jiayi Hu
źródło
I ta „kwestia zakresu” ma miejsce np. Gdy używasz destrukturyzacji argumentów, jak function({ login })przekazanie reqjako pierwszego argumentu. Twoje rozwiązanie zadziałało dla mnie, dzięki
Manuel Di Iorio
Tak, to jak thisdziała w Javascript. Jeśli nie wywołasz funkcji jako metody obiektowej, thisbędzie undefined(lub windoww przeglądarce)
Jiayi Hu
Wskazówka dla wszystkich, którzy czytają tę odpowiedź i jej nie rozumieją ... jeśli zbadasz Function.prototype.call, Function.prototype.applyjak thisdziała JavaScript i zasady prototypowego dziedziczenia, awansujesz na poziom Javascript Guru :)
Stijn de Witt
Na zdrowie, miałem nadzieję, że to będzie tak proste, jakutil.promisify(req.login.bind(req));
Julian H. Lam
4

Pomogło mi również umieszczenie tras PO konfiguracji plików 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);
Michał Dobi Dobrzański
źródło
masz jakiś pomysł, dlaczego trasy inicjujące po konfiguracji działają?
Ishu
To rozwiązało mój problem. Przeniosłem wszystkie trasy. Używaj połączeń po wszystkim, co dotyczy paszportu.
Nick Van Brunt
2

Odpowiedź Petera Lyonsa pomogła mi go rozwiązać, ale rozwiązałem go w nieco inny sposób.

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

Spójrz na moje repozytorium GitHub dla całego kodu, a nie tylko fragmentu kodu tutaj.

Isak La Fleur
źródło
1

W moim przypadku (ten sam komunikat o błędzie), opracowywałem niestandardową strategię i nie potrzebuję sesji . Po prostu zapomniałem dodać oprogramowanie pośredniczące session: falsetras authenticate.

  app.post('/api/public/auth/google-token',
    passport.authenticate('google-token', {
      session: false
    }),
    function (req: any, res) {
      res.send("hello");
    }
  );
ruwan800
źródło
0

Umieść app.use(passport.initialize())oprogramowanie pośrednie przed produktem pośrednim app.routeri działa jak urok

Sai kiran Kavali
źródło