如何使用快递管理某些路线的 Passport JS 会话

How can I manage sessions with Passport JS for some routes using express?

本文关键字:Passport JS 会话 些路 何使用 快递 管理      更新时间:2023-09-26

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

但是,主要问题是,即使Passport正在做它的工作,无论我没有先登录,我仍然可以直接去localhost/registro

当有人尝试访问localhost/registro如果未首先完成登录和身份验证,则应将其重定向到起始页。

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

我对我应该尝试什么、cookie、会话等感到非常困惑。 此外,在新的快速版本中,中间件的工作方式与以前不同。

这是我的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);
    });
  });
}));

Express "chains" route methods。在Express中保护路由背后的基本思想.js是在允许请求进入预期路由之前检查a&a的方法。有几种方法可以做到这一点:

方法

1:将身份验证方法添加到路由声明中

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:在哪里声明所需的身份验证方法如果您计划将路由处理程序放置在多个.js文件中,最好将 require auth mehtod 也放在单独的 .js 文件中,并在适当的时候需要它。

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

编辑 2:会话如何在快递.js和护照中工作.js

从 Passport.js 文档中,您首先需要在护照会话之前配置快速会话:

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

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

与 serializeUser 和 反序列化用户 方法一起,此时 Passport 将在请求中放置一个 .user。

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

注意 2:我在获取序列化用户和反序列化用户方法以使用 Passport-Saml 时遇到了问题。如果是这种情况,只需自己管理会话即可。