簡體   English   中英

Node JS + Passport 登錄

[英]Node JS + Passport login

我正在嘗試將我的第一個節點 js 應用程序配置為使用通行證登錄。

所以首先要做的事情。 我創建了一個/app/config/express.js文件來配置 express 的東西。 所以我的app.js更簡單:

var app = require('./app/config/express')();

app.listen(3001, function(){
    console.log("Servidor rodando");
});

好,這很酷。 但! 我的 express.js 文件太大了。 也許你可以給我一些關於如何重構它的提示?

我添加了一些帶有一些問題的評論,我很樂意讓這段代碼變得更好。

var express = require('express');
var load = require('express-load');
var expressValidator = require('express-validator');
var bodyParser = require('body-parser');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var session = require('express-session');
var flash = require("connect-flash");

module.exports = function() {

    // PLEASE READ 1
    //
    // 
    // Functions to organize code better.
    // PS: if this functions are outside "module.exports", then Express
    // doesnt 'inject' the 'app.infra' variable .... 
    // Is there a workaround to move these functions outta here?
    //
    // 
    function configureAuth(){
        passport.use(new Strategy({
            passReqToCallback : true
          },
          function(req, username, password, cb) {

            var connection = app.infra.connectionFactory();
            var userDao = new app.infra.dao.UserDao(connection);

            userDao.login(username, password, function(err, user){
              if (err) {
                return cb(err);
              }

              if (!user) {
                return cb(null, false);
              }


              return cb(null, user);
            });

            connection.end();

          }));

        //
        // 
        // HERE IT IS!
        //
        //
        passport.serializeUser(function(user, cb) {
          cb(null, user.id);
        });

        passport.deserializeUser(function(id, cb) {
            cb(null, user);
        });
    }

    function configureExpressLibs(app){
        app.set('view engine', 'ejs');
        app.set('views','./app/views');

        app.use('/static', express.static('./app/public'));
        app.use(flash());

        app.use(bodyParser.urlencoded({extended: true}));
        app.use(bodyParser.json());
        app.use(expressValidator());

        app.use(session({
            secret: '086this 54is 23unkowned 67',
            resave: false,
            saveUninitialized: false
        }));

        app.use(passport.initialize());
        app.use(passport.session());
    }

    function configureErrors(app){
        app.use(function(err, req, res, next) {
            console.error(err.stack)
            next(err)
        });

        app.use(function(req,res,next){
            res.status(404).render('errors/404');
            next();
        });


        app.use(function(error, req,res,next){
            res.status(500).render('errors/500');
            next();
        });
    }

     // PLEASE READ 2
     // 
     // 
     //  I've moved this to 'LoginController.js' in my routes folder but
     //  I didnt work... So I moved it here. Is there a work around?
     //
     //
    function configureLoginRoutes(app){

      function redirectToIndexIfLoggedIn(req, res, next) {
        if (req.isAuthenticated())
          res.redirect('/');

        return next();
      }

      app.get('/login', redirectToIndexIfLoggedIn, function(req, res){
        res.render('login/login');
      });

      app.post('/login', passport.authenticate('local', {
        successRedirect : '/',
        failureRedirect : '/login',
        failureFlash : 'Invalid username or password.'
        }));

      app.get('/logout', function(req, res){
          req.logout();
          req.session.destroy();
          res.redirect('/');
      });
    }


    var app = express();

    configureExpressLibs(app);

    configureAuth();

    configureLoginRoutes(app);


    load('routes',{cwd: 'app'})
        .then('infra')
        .into(app);

    configureErrors(app);

    return app;
}

所以現在的問題是,當我登錄時(用戶正確或錯誤無關緊要),我得到:

Error: Failed to serialize user into session

我用谷歌搜索了一下,發現原因是人們忘記了實現“serializeUser”。 但我做到了。 請檢查上面代碼中帶有“這里是”的注釋。

謝謝你們。 對不起,大代碼。 但我正在學習,我希望在你的幫助下讓事情變得更好。

編輯我的反序列化方法是錯誤的。 我使用以下方法修復它:

    passport.deserializeUser(function(id, cb) {
      var connection = app.infra.connectionFactory();
      var userDao = new app.infra.dao.UserDao(connection);

      userDao.findById(id, function(err, user) {
        done(err, user);
      });

      connection.end();

    });

但應用程序仍然失敗。 同樣的錯誤。

編輯解決方案

原來我的實現是錯誤的。 你看,mysql 總是返回一個數組。 因此,我像這樣更正了我的代碼:

      function(req, username, password, cb) {

        var connection = app.infra.connectionFactory();
        var userDao = new app.infra.dao.UserDao(connection);

        userDao.login(username, password, function(err, user){
          if (err) {
            return cb(err);
          }

          if (!user) {
            return cb(null, false);
          }

          // HERE

          return cb(null, user[0]);
        });

        connection.end();

      }));

和這里:

    passport.deserializeUser(function(id, cb) {
      var connection = app.infra.connectionFactory();
      var userDao = new app.infra.dao.UserDao(connection);

      userDao.findById(id, function(err, user) {
         // HERE
         cb(err, user[0]);
      });

      connection.end();

    });
} 

我認為當您調用cb(null,user)時,您的 this.user 沒有設置在 deserializeUser 中cb(null,user)因此在 app.use(passport.session()) 之后創建您自己的中間件以將其放入this.user如下所示:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

干杯:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM