passport.js middleware passport.initialize () tidak digunakan

103

Saya menggunakan node dengan express + mongoose dan mencoba menggunakan passport.js dengan restful api.
Saya terus mendapatkan pengecualian ini setelah otentikasi berhasil (saya melihat url panggilan balik di browser):

/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

Saya telah membaca bahwa saya harus meletakkan app.use(passport.initialize());dan app.use(passport.session());sebelumnya app.use(app.router);dan inilah yang saya lakukan. Ini express.js saya yang mendaftarkan middlewares:

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

Apa yang salah?

PEMBARUAN Menurut @Peter Lyons saya telah mengubah urutan konfigurasi menjadi berikut, tetapi saya masih mendapat kesalahan yang sama:

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
sumber
Versi Express 4.x tidak mendukung beberapa metode. Lihat github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Jawaban:

206

Ikuti contoh untuk menghindari neraka middleware rusak yang membuatnya begitu mudah untuk dimasuki. Langsung dari dokumen. Perhatikan bagaimana milik Anda tidak sama persis dengan ini.

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

Docs

  1. cookieParser
  2. sidang
  3. passport.initialize
  4. passport.session
  5. app.router

Kamu

  1. passport.initialize
  2. passport.session
  3. cookieParser
  4. sidang
  5. app.router
Peter Lyons
sumber
Saya telah mengubahnya menjadi apa yang Anda sarankan tetapi masih memberikan kesalahan ini. Saya memperbarui pertanyaan saya dengan file express.js baru /
Naor
7
Jadi kode yang Anda miliki di sini bukanlah kode tingkat atas Anda. Sebelumnya dalam program Anda yang Anda membuat panggilan ke app.get, app.post, dll? Itu akan menyebabkan router ditambahkan ke tumpukan lebih awal dari yang Anda inginkan. Tunjukkan kepada kami SEMUA kode yang dimulai dengan saat Anda menjalankan express()fungsi untuk mendapatkan appobjek Anda . Itu tebakan saya yang kedua.
Peter Lyons
3
Saya telah memperhatikan bahwa app.use (app.router); dipanggil setelah paspor diinisialisasi tetapi saya memanggil: require ('./ config / routes') (app, passport, auth); sebelum menelepon untuk mengekspresikan konfigurasi. Beralih di antara kedua garis menyelesaikan masalah. Terima kasih!
Naor
1
Ini berhasil untuk saya! Tapi kenapa middleware harus diatur seperti itu?
Anthony To
3
Dengan desain sehingga Anda dapat mengandalkan prasyarat yang sedang dilakukan. Sesi tidak akan berfungsi jika cookieParser belum mengurai cookie.
Peter Lyons
12

Dalam kasus saya (pesan kesalahan yang sama), saya sama sekali lupa menambahkan inisialisasi paspor:

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

PEMBARUAN: Hanya bekerja hingga versi ekspres 3, versi 4 tidak lagi mendukung app.configure ()

Matthias M
sumber
1
App.configure tidak dapat digunakan lagi. github.com/strongloop/express/wiki/… .. Mereka harus memperbarui dokumen paspor. Baik?
jack blank
9

Dalam kasus saya kesalahan itu karena saya mencoba untuk promisify req.logintanpa mengikat thisuntuk req, jadi ketika fungsi dipanggil itu tidak bisa menemukan passportpengaturan. Solusinya mengikat req.login.bind(req)sebelum meneruskannya promisifyjika Anda menggunakan Node v8.

Jiayi Hu
sumber
Dan "masalah cakupan" ini terjadi misalnya saat Anda menggunakan argumen yang merusak seperti function({ login })meneruskan reqsebagai argumen pertama. Solusi Anda berhasil untuk saya, terima kasih
Manuel Di Iorio
Yup itu cara thiskerja di Javascript. Jika Anda tidak memanggil fungsi sebagai metode objek maka thisakan undefined(atau windowdi browser)
Jiayi Hu
Kiat bagi siapa pun yang membaca jawaban ini dan tidak memahaminya ... jika Anda menyelidiki Function.prototype.call,, Function.prototype.applybagaimana cara thiskerja Javascript dan prinsip di balik pewarisan prototipe, Anda akan mempromosikannya ke tingkat Javascript Guru dalam proses :)
Stijn de Witt
Cheers, saya berharap ini akan sesederhanautil.promisify(req.login.bind(req));
Julian H. Lam
4

Apa yang telah membantu saya juga adalah menempatkan rute SETELAH konfigurasi 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
sumber
mendapat ide mengapa rute init setelah konfigurasi berfungsi?
Ishu
Ini memperbaiki masalah saya. Saya memindahkan semua rute. Gunakan panggilan setelah apa pun yang berhubungan dengan paspor.
Nick Van Brunt
2

Jawaban Peter Lyons membantu saya untuk menyelesaikannya, tetapi saya menyelesaikannya dengan cara yang sedikit berbeda.

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

Lihat repo GitHub saya untuk seluruh kode dan bukan hanya cuplikan kode di sini.

Isak La Fleur
sumber
1

Dalam kasus saya (pesan kesalahan yang sama), saya sedang mengembangkan strategi kustom dan saya tidak perlu menggunakan sesi . Saya baru saja lupa menambahkan middleware session: falserute saya authenticate.

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