passport.js passport.initialize () มิดเดิลแวร์ไม่ได้ใช้งาน


104

ฉันใช้ node กับ 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

คำตอบ:


207

ทำตามตัวอย่างเพื่อหลีกเลี่ยงนรกมิดเดิลแวร์ที่ไม่อยู่ในลำดับที่ 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. cookieParser
  2. เซสชัน
  3. หนังสือเดินทางเริ่มต้น
  4. passport.session
  5. app.router

คุณ

  1. หนังสือเดินทางเริ่มต้น
  2. passport.session
  3. cookieParser
  4. เซสชัน
  5. app.router

ฉันได้เปลี่ยนเป็นสิ่งที่คุณแนะนำแล้ว แต่ก็ยังแสดงข้อผิดพลาดนี้ ฉันปรับปรุงคำถามของฉันกับแฟ้ม express.js ใหม่ /
Naor

7
ดังนั้นรหัสที่คุณมีอยู่ที่นี่จึงไม่ใช่รหัสระดับบนสุดของคุณ ก่อนหน้านี้ในโปรแกรมของคุณที่คุณโทรออกใด ๆ เพื่อapp.get, app.postetc? สิ่งเหล่านี้จะทำให้เราเตอร์ถูกเพิ่มลงในสแต็กเร็วกว่าที่คุณตั้งใจ แสดงรหัสผู้เปิดเผยทั้งหมดโดยเริ่มจากเมื่อคุณเรียกใช้express()ฟังก์ชันเพื่อรับappวัตถุของคุณ นั่นเป็นการเดาครั้งที่ 2 ของฉัน
Peter Lyons

3
ฉันสังเกตเห็นว่า app.use (app.router); ถูกเรียกหลังจากเริ่มต้นหนังสือเดินทาง แต่ฉันเรียก: ต้องใช้ ('./ config / route') (app, passport, auth); ก่อนที่จะโทรเพื่อแสดงการกำหนดค่า การสลับระหว่างทั้งสองบรรทัดช่วยแก้ปัญหาได้ ขอบคุณ!
Naor

1
สิ่งนี้ได้ผลสำหรับฉัน! แต่ทำไมตัวกลางถึงต้องเรียงลำดับแบบนั้น?
Anthony ถึง

3
ด้วยการออกแบบเพื่อให้คุณสามารถพึ่งพาข้อกำหนดเบื้องต้นที่กำลังดำเนินการอยู่ เซสชันจะไม่ทำงานหาก cookieParser ยังไม่ได้แยกวิเคราะห์คุกกี้
Peter Lyons

12

ในกรณีของฉัน (ข้อความแสดงข้อผิดพลาดเดียวกัน) ฉันลืมเพิ่มการเริ่มต้นหนังสือเดินทางเลย:

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

อัปเดต: ทำงานได้ถึง express เวอร์ชัน 3 เท่านั้นเวอร์ชัน 4 ไม่รองรับ app.configure () อีกต่อไป


1
ไม่สามารถใช้ App.configure ได้อีกต่อไป github.com/strongloop/express/wiki/… .. พวกเขาควรปรับปรุงเอกสารหนังสือเดินทาง ขวา?
แจ็คเปล่า

9

ในกรณีของข้อผิดพลาดได้เพราะผมพยายามที่จะ promisify req.loginโดยไม่ต้องมีผลผูกพันthisไปreqดังนั้นเมื่อฟังก์ชั่นที่เรียกว่ามันไม่สามารถพบกับpassportการตั้งค่า โซลูชันมีผลผูกพันreq.login.bind(req)ก่อนที่จะส่งต่อไปpromisifyหากคุณใช้ Node v8


และ "ปัญหาขอบเขต" นี้เกิดขึ้นเช่นเมื่อคุณใช้อาร์กิวเมนต์ทำลายโครงสร้างเช่นการfunction({ login })ส่งreqอาร์กิวเมนต์ as first วิธีแก้ปัญหาของคุณได้ผลสำหรับฉันขอบคุณ
Manuel Di Iorio

ใช่มันเป็นวิธีการthisทำงานใน Javascript หากคุณไม่เรียกใช้ฟังก์ชันว่า object method thisจะเป็นundefined(หรือwindowในเบราว์เซอร์)
Jiayi Hu

เคล็ดลับสำหรับทุกคนที่อ่านคำตอบนี้และไม่เข้าใจมัน ... ถ้าคุณตรวจสอบFunction.prototype.call, Function.prototype.applyวิธีthisการทำงานใน Javascript และหลักการที่อยู่เบื้องหลังมรดกแม่บทคุณจะส่งเสริมให้ระดับของจาวาสคริคุรุในกระบวนการ :)
Stijn เดอวิตต์

ไชโยฉันหวังว่ามันจะเรียบง่ายเหมือนutil.promisify(req.login.bind(req));
Julian H. Lam

4

สิ่งที่ช่วยฉันได้คือการกำหนดเส้นทางหลังจากกำหนดค่าคุกกี้ :

// 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 หลังจากกำหนดค่าจึงทำงานได้
Ishu

สิ่งนี้ช่วยแก้ปัญหาของฉันได้ ฉันย้ายเส้นทางทั้งหมดใช้การโทรหลังจากอะไรก็ตามที่เกี่ยวข้องกับหนังสือเดินทาง
Nick Van Brunt

2

คำตอบของ Peter Lyons ช่วยฉันแก้ปัญหาได้ แต่ฉันแก้ไขด้วยวิธีที่แตกต่างออกไปเล็กน้อย

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

ดูที่repo 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");
    }
  );

0

วางapp.use(passport.initialize())มิดเดิลแวร์ไว้ด้านหน้าของapp.routerเครื่องกลางและใช้งานได้อย่างมีเสน่ห์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.