📌  相关文章
📜  节点 |使用 Passportjs 和passport-local-mongoose 进行身份验证

📅  最后修改于: 2022-05-13 01:56:57.338000             🧑  作者: Mango

节点 |使用 Passportjs 和passport-local-mongoose 进行身份验证

Passport 是 Node.js 的身份验证中间件。它旨在服务于单一目的,即对请求进行身份验证。将用户密码作为原始字符串存储在数据库中是不切实际的,但将密码散列然后将它们存储到数据库中是一种很好的做法。但是使用passport-local-mongoose,您不必使用crypto 模块散列密码,passport-local-mongoose 将为您完成所有工作。如果您使用passport-local-mongoose,该模块将在数据库中自动生成salt 和hash 字段。您将没有密码字段,相反,您将拥有 salt 和 hash。

为什么需要对密码进行加盐

如果用户只是简单地散列他们的密码,并且如果数据库中的两个用户具有相同的密码,那么他们将具有相同的散列值。如果任何一个密码被黑客入侵,那么黑客可以使用相同的密码访问每个帐户,因为具有相同密码的用户将具有相同的哈希字段。
所以在我们对它进行散列之前,我们预先添加一个唯一的字符串。不是秘密,只是一些独特的东西。所以每种盐的哈希值都完全不同。

执行操作的步骤

首先让我们生成一个 express 应用程序,然后安装所需的模块



> npm install passport passport-local mongoose passport-local-mongoose --save

1.首先创建如下目录结构:

--model
----user.js
--route
----user.js
--app.js

2.创建定义用户架构的模型/user.js文件

// importing modules
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
  
  
var UserSchema = new Schema({   
    email: {type: String, required:true, unique:true},
    username : {type: String, unique: true, required:true},
});
  
// plugin for passport-local-mongoose
UserSchema.plugin(passportLocalMongoose);
  
// export userschema
 module.exports = mongoose.model("User", UserSchema);

请注意,在此模式中,我们没有像平常那样为密码添加任何字段。这是因为passport-local-mongoose 不需要它。在这里,我们没有添加任何方法来散列我们的密码或比较我们的密码,因为我们通常进行身份验证,因为passport-local-mongoose 将为我们完成所有这些。

3.在 app.js 中配置 Passport/Passport-Local :

首先在app.js中,你必须初始化passport

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

护照将保持持续的登录会话。为了使持久会话在通行证中工作,经过身份验证的用户必须序列化到会话并在发出后续请求时反序列化。使用护照本地猫鼬是

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

如果您没有将passport-local-mongoose 与护照一起使用,序列化和反序列化代码可能会略有不同。

现在我们必须定义护照的策略。对于护照本地猫鼬,代码是



const User = require('./models/user');
  
const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(User.authenticate()));

如果您仅使用没有passport-local-mongoose的passport,则本地策略可能会大不相同,即)您将不得不编写代码来比较密码等等。这里只有这 2 行就足够了

4.创建路由/user.js文件:

首先导入用户架构以及其他必要的模块

// importing modules 
const express = require('express'); 
const router = express.Router(); 
    
// importing User Schema 
const User = require('../model/user');

5.报名方式:

现在注册代码应该是

router.post('/login', function(req, res) {
      
    Users=new User({email: req.body.email, username : req.body.username});
  
          User.register(Users, req.body.password, function(err, user) {
            if (err) {
              res.json({success:false, message:"Your account could 
              not be saved. Error: ", err}) 
            }else{
              res.json({success: true, message: "Your account has 
               been saved"})
            }
          });
});

在上面的代码中,我们没有在新用户中定义我们的密码。相反,我们将密码与 User.Register() 一起使用,这是一个passport-local-mongoose函数。现在,如果您检查已保存用户的数据库,它将如下所示

{
    "_id" : ObjectId("5ca8b66535947f4c1e93c4f1"),
    "username" : "username you gave",
    "email" : "email you gave",
    "salt" : "4c8f6e009c4523b23553d9479e25254b266c3b7dd2dbc6d4aaace01851c9687c",
    "hash" : "337de0df58406b25499b18f54229b9dd595b70e998fd02c7866d06d2a6b25870d23650
cdda829974a46e3166e535f1aeb6bc7ef182565009b1dcf57a64205b5548f6974b77c2e3a3c6aec5360d
55f9fcd3ffd6fb99dce21aab021aced72881d3720f6a0975bfece4922282bb748e0412955e0afa2fb8c9
f5055cac0fb01a4a2288af2ce2a6563ed9b47852727749c7fe031b6b7fbb726196dbdfeeb6766d5cba6a
055f66eeacce685daef8b6c1aed0108df511c92d49150efb6473ee71c5149dd06bfb4f73cb60f9815af0
1e02fde8d8ed822bb3a55f040237cf80de0b1534de6bbafcb53f882c6eb03de4b4aa307828974eb51261
661efb5155e68ad0e593c0f5fab7d690c2257df4369e9d5ac7e2fc93b5b014260c6f8fbb01034b3f85ec
f11e086e9bf860f959d0e2104a1f825d286c99d3fc6f62505d1fde8601345c699ea08dcc071e5547835c
16957d3830998a10762ebd143dc557d6a96e4b88312e1e4c51622fef3939656c992508e47ddc148696df
3152af76286d636d4814a0dc608f72cd507c617feb77cbba36c5b017492df5f28a7a3f3b7881caf6fb4a
9d6231eca6edbeec4eb1436f1e45c27b9c2bfceccf3a9b42840f40c65fe499091ba6ebeb764b5d815a43
d73a888fdb58f821fbe5f7d92e20ff8d7c98e8164b4f10d5528fddbcc7737fd21b12d571355cc605eb36
21f5f266f8e38683deb05a6de43114",
    "__v" : 0
}

您会注意到根本没有密码字段,而是passport-local-mongoose 为您创建了salt 和hash,您也不必在架构中定义salt 和hash 字段。 Passport-local-mongoose 将保持您的用户名唯一,即如果用户名已经存在,它将给出“UserExistsError”。

5.登录:

现在登录

userController.doLogin = function(req, res) {
  if(!req.body.username){
    res.json({success: false, message: "Username was not given"})
  } else {
    if(!req.body.password){
      res.json({success: false, message: "Password was not given"})
    }else{
      passport.authenticate('local', function (err, user, info) { 
         if(err){
           res.json({success: false, message: err})
         } else{
          if (! user) {
            res.json({success: false, message: 'username or password incorrect'})
          } else{
            req.login(user, function(err){
              if(err){
                res.json({success: false, message: err})
              }else{
                const token =  jwt.sign({userId : user._id, 
                   username:user.username}, secretkey, 
                      {expiresIn: '24h'})
                res.json({success:true, message:"Authentication 
                    successful", token: token });
              }
            })
          }
         }
      })(req, res);
    }
  }
};

6.重置或更改密码:

您可以使用passport-local-mongoose 中的2 个简单功能来重置或更改密码。它们是setPassword函数和 changePassword 函数。通常 setPassword 在用户忘记密码时使用,changePassword 在用户想要更改密码时使用。

对于 setPassword 代码是

// user is your result from userschema using mongoose id
 user.setPassword(req.body.password, function(err, user){ ..

换密码

// user is your result from userschema using mongoose id
  user.changePassword(req.body.oldpassword, req.body.newpassword, function(err) ...

您可以直接在路由器文件中调用它们