passport.js passport.initialize () phần mềm trung gian không được sử dụng


103

Tôi đang sử dụng nút với express + mongoose và cố gắng sử dụng passport.js với api yên tĩnh.
Tôi tiếp tục nhận được ngoại lệ này sau khi xác thực thành công (tôi thấy url gọi lại trên trình duyệt):

/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

Tôi đã đọc rằng tôi nên đặt app.use(passport.initialize());app.use(passport.session());trước đây app.use(app.router);và đây là những gì tôi đã làm. Đây là express.js của tôi đăng ký phần mềm trung gian:

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

Chuyện gì thế?

CẬP NHẬT Theo @Peter Lyons, tôi đã thay đổi thứ tự cấu hình thành như sau, nhưng vẫn gặp lỗi tương tự:

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

Phiên bản Express 4.x không hỗ trợ một số phương pháp. Xem github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Câu trả lời:


206

Hãy làm theo ví dụ để tránh phần mềm trung gian không theo thứ tự mà express giúp bạn dễ dàng nhập vào. Trực tiếp từ tài liệu. Lưu ý cách của bạn không khớp chính xác với điều này.

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. phiên họp
  3. passport.initialize
  4. passport.session
  5. app.router

Bạn

  1. passport.initialize
  2. passport.session
  3. cookieParser
  4. phiên họp
  5. app.router

Tôi đã thay đổi nó thành những gì bạn đề xuất nhưng nó vẫn xuất hiện lỗi này. Tôi đã cập nhật câu hỏi của mình bằng tệp express.js mới /
Naor

7
Vì vậy, mã bạn có ở đây không phải là mã cấp cao nhất của bạn. Trước đó trong chương trình của bạn được bạn thực hiện bất kỳ cuộc gọi đến app.get, app.post, vv? Những điều đó sẽ khiến bộ định tuyến được thêm vào ngăn xếp sớm hơn bạn dự định. Cho chúng tôi xem TẤT CẢ mã thú vị bắt đầu khi bạn gọi express()hàm để lấy appđối tượng của mình . Đó là dự đoán thứ 2 của tôi.
Peter Lyons

3
Tôi đã nhận thấy rằng app.use (app.router); được gọi sau khi khởi tạo hộ chiếu nhưng tôi gọi: request ('./ config / route') (app, passport, auth); trước khi gọi để thể hiện cấu hình. Chuyển đổi giữa cả hai dòng đã giải quyết được vấn đề. Cảm ơn!
Naor

1
Điều này đã làm việc cho tôi! Nhưng tại sao phần mềm trung gian lại phải theo thứ tự như vậy?
Anthony Đến

3
Theo thiết kế để bạn có thể dựa vào các điều kiện tiên quyết đang được thực hiện. Phiên sẽ không hoạt động nếu cookieParser chưa phân tích cú pháp cookie.
Peter Lyons

12

Trong trường hợp của tôi (cùng một thông báo lỗi), tôi đã quên thêm các lần khởi tạo hộ chiếu:

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

CẬP NHẬT: Chỉ hoạt động lên phiên bản express 3, phiên bản 4 không hỗ trợ app.configure () nữa


1
App.configure không thể được sử dụng nữa. github.com/strongloop/express/wiki/… .. Họ nên cập nhật tài liệu hộ chiếu. đúng?
jack trống

9

Trong trường hợp của tôi, lỗi là do tôi đang cố gắng quảng bá req.loginmà không liên kết thisvới req, vì vậy khi hàm được gọi, nó không thể tìm thấy passportcài đặt. Giải pháp được ràng buộc req.login.bind(req)trước khi chuyển nó đến promisifynếu bạn đang sử dụng Node v8.


Và "vấn đề phạm vi" này xảy ra, ví dụ khi bạn sử dụng cấu trúc đối số như function({ login })truyền reqđối số làm đối số đầu tiên. Giải pháp của bạn làm việc cho tôi, cảm ơn
Manuel Di Iorio

Đúng, đó là cách thishoạt động trong Javascript. Nếu bạn không gọi hàm dưới dạng phương thức đối tượng thì thissẽ undefined(hoặc windowtrong trình duyệt)
Jiayi Hu

Mẹo cho bất kỳ ai đọc câu trả lời này và không hiểu nó ... nếu bạn điều tra Function.prototype.call, Function.prototype.applycách thishoạt động trong Javascript và các nguyên tắc đằng sau kế thừa nguyên mẫu, bạn sẽ thăng cấp lên cấp độ của Javascript Guru trong quá trình này :)
Stijn de Witt

Chúc mừng, tôi đã hy vọng nó sẽ đơn giản nhưutil.promisify(req.login.bind(req));
Julian H. Lam

4

Điều đã giúp tôi cũng là đặt các tuyến SAU khi cấu hình 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);

có bất kỳ ý tưởng tại sao các tuyến đường init đó sau khi cấu hình hoạt động?
Ishu

Điều này đã khắc phục sự cố của tôi. Tôi đã di chuyển tất cả các cuộc gọi route.use sau bất cứ thứ gì liên quan đến hộ chiếu.
Nick Van Brunt

2

Câu trả lời của Peter Lyons đã giúp tôi giải quyết nó, nhưng tôi đã giải quyết nó theo cách khác.

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

Hãy xem repo GitHub của tôi để biết toàn bộ mã chứ không chỉ đoạn mã ở đây.


1

Trong trường hợp của tôi (cùng một thông báo lỗi), tôi đang phát triển một chiến lược tùy chỉnh và tôi không cần sử dụng phiên . Tôi vừa quên thêm phần mềm trung gian session: falsetuyến đường của mình authenticate.

  app.post('/api/public/auth/google-token',
    passport.authenticate('google-token', {
      session: false
    }),
    function (req: any, res) {
      res.send("hello");
    }
  );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.