【问题标题】:How can I manage sessions with Passport JS for some routes using express?如何使用 Express 管理某些路由的 Passport JS 会话?
【发布时间】:2014-07-08 05:54:28
【问题描述】:

我低于 express node.js 服务器代码 使用 Passport。我的整个路由定义依赖于使用 mongo-db 的 MongoDB 连接,但 Passport 使用的模型是通过 mongoose 的另一个连接完成的。我提到这两个细节是因为我认为它也应该以更好的方式编码。

但是,主要问题是,即使 Passport 可以正常工作,我仍然可以直接转到 localhost/registro,无论我没有先登录

当有人尝试访问 localhost/registro 时,如果没有先登录和验证,则应该将其重定向到起始页。

我关心它的安全实施,我还想在会话期间获得一些关于用户的信息。

我对我应该尝试什么、cookie、会话等感到很困惑。除了在新的 express 版本中,中间件的工作方式与以前不同。

这是我的server.js

var express =       require('express')
var mongodb =       require('mongodb')
var mongoose =      require('mongoose')
var bodyParser =    require('body-parser')
var passport =      require('passport')
var LocalStrategy = require('passport-local').Strategy;

var app = express()

var BSON = mongodb.BSONPure

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

app.use(express.static(__dirname+"/public"))
app.use(bodyParser())

var MongoDBClient = mongodb.MongoClient

mongoose.connect('mongodb://localhost/psicologosTuxtepecDB')

var Schema = mongoose.Schema
var userCredential = new Schema({

    username:   String,
    password:   String

},  {
    collection:     'members'
})

var userCredentials = mongoose.model('members', userCredential)

passport.serializeUser(function(user, done) {
  done(null, user);
})

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

passport.use(new LocalStrategy(function(username, password, done) {
  process.nextTick(function() {
    userCredentials.findOne({
      'username': username, 
    }, function(err, user) {
      if (err) {
        return done(err);
      }

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

      if (user.password != password) {
        return done(null, false);
      }

      return done(null, user);
    });
  });
}));

MongoDBClient.connect("mongodb://localhost/psicologosTuxtepecDB", function (error, psicologosTuxtepecDB) {

    if (error) {

        console.log("We've got a connection error, so far we should take this function better for a correct debug")
    }

    else {

        console.log("Connection to psicologosTuxtepecDB has been successful")

        // Seleccionamos una colección
        var psicologosCollection = psicologosTuxtepecDB.collection("psicologos")

        app.get('/registro', function(request,response) {

            response.sendfile("public/html/registro.html")
        })

        // Cuando nos hagan una petición HTTP de tipo POST en la ruta psicologos...
        app.post("/psychos", function(request, response) {

            var psychologist = {

                personalData:           request.body._personalData,
                professionalData:       request.body._professionalData,
                professionalInterests:  request.body._professionalInterests
            }


            psicologosCollection.insert(psychologist, function(error, responseFromDB) {

                if (error) {response.send(responseFromDB)}

                console.log("Se ha insertado: "+ JSON.strinfigy(responseFromDB))
                response.send(responseFromDB)
            })
        })

        app.get("/psychos/:id", function(request, response) {

            var id = new BSON.ObjectID(peticion.params.id)

            psicologosCollection.findOne( 
                                            {'_id':id},
                                            function(error,responseFromDB) { if (error) {response.send(responseFromDB)} response.send(responseFromDB)}
                                        )
        })

        app.get("/psychos", function(request,response) {

            psicologosCollection.find().toArray(function(error,responseFromDB) {
                if (error) {response.send(responseFromDB)}
                response.send(responseFromDB)
            })
        })

        app.post('/login',
          passport.authenticate('local', {
            successRedirect: '/loginSuccess',
            failureRedirect: '/loginFailure'
          })
        )

        app.get('/loginFailure', function(req, res, next) {
            res.redirect('/')
        })

        app.get('registro', function(request, response) {
            response.sendfile('public/html/registro.html')
        })

        app.get('/loginSuccess', function(req, res, next) {
          res.redirect('/registro')

    })      

    app.listen(80, function () {
        console.log("app escuchando en el puerto Maricela fecha de nacimiento DDMM")
    })
}

})

这些是我的护照声明:

app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
  done(null, user);
})

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

passport.use(new LocalStrategy(function(username, password, done) {
  process.nextTick(function() {
    userCredentials.findOne({
      'username': username, 
    }, function(err, user) {
      if (err) {
        return done(err);
      }

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

      if (user.password != password) {
        return done(null, false);
      }

      return done(null, user);
    });
  });
}));

【问题讨论】:

    标签: javascript node.js session express passport.js


    【解决方案1】:

    表达“链”路由方法。在 Express.js 中保护路由的基本思想是有一个方法在允许请求继续到预期的路由之前检查 a&a。有几种方法可以做到这一点:

    方法一:在路由声明中加入auth方法

    function requireAuth(req,res,next){
       if user is authenticated
          next();
       else
          res.send(401);
    }
    
    app.get('/registro', requireAuth, function(request, response) {
                response.sendfile('public/html/registro.html')
            })
    

    方法 2:为您的身份验证声明路由处理程序

    app.get('/registro', function(req,res,next){
           if user is authenticated
              next();
           else
              res.send(401);
    })
    
    app.get('/registro', function(request, response) {
                    response.sendfile('public/html/registro.html')
                })
    

    方法3:使用app.use()代替动词

    使用这种方法,您需要考虑 app.router 何时插入中间件。

    编辑 1:在哪里声明 require auth 方法 如果您计划将路由处理程序放在多个 .js 文件中,最好将您的 require auth mehtod 也放在一个单独的 .js 文件中,并在适当的地方使用它。

    否则,您可以将其与其他所有内容放在同一个文件中。

    编辑 2:会话如何在 Express.js 和 Passport.js 中工作

    来自Passport.js documentation,首先需要在passport session之前配置express session:

    app.use(express.session({ secret: 'keyboard cat' }));  
    app.use(passport.initialize());   
    app.use(passport.session());
    

    注意:您可能应该考虑使用内存存储以外的其他东西进行会话管理。

    与 serializeUser 和 deserializeUser 方法一起,此时 Passport 将在请求中放置一个 .user。

    您还可以使用req.isAuthenticated() 来确定用户是否经过身份验证。

    注意 2:我在让 serializeUser 和 deserializeUser 方法与 Passport-Saml 一起工作时遇到了问题。如果是这种情况,请自行管理会话。

    【讨论】:

    • 谢谢。你能扩展一下你的例子吗?在方法 1 中,从哪里调用 requireAuth?在第一个和第二个中,session 会在哪里声明?
    • 谢谢,我得到了 MongoDB,如何在 那里 存储临时会话?
    • @diegoaguilar Connect-Mongo?这与最初的问题相差甚远。你最好单独问一下。
    • 我对此发表评论,因为我知道 Mongo 可以用于它,甚至 Redis。我猜 Connect-Mongo 是一个可以用 npm 获得的模块
    • 是的,可以通过 npm 获得。
    猜你喜欢
    • 2013-03-30
    • 2012-06-18
    • 2019-12-25
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    相关资源
    最近更新 更多