【问题标题】:Passport JS using express, authentication on 'Local' strategy returns "Missing Credentials" every timePassport JS 使用 express,'Local' 策略的身份验证每次都返回“Missing Credentials”
【发布时间】:2020-02-23 22:04:28
【问题描述】:

我的问题是,在 POST 上,每当我尝试使用“本地”策略进行身份验证时,都会收到“缺少凭据”错误。我最初认为这是 body-parser 的问题,但即使在一些关于强制 urlencoded: true/false 的建议之后,我仍然没有得到任何不同的结果。除了无关的 req.body 之外,我的控制台日志也没有返回任何实质性内容,我真的不确定此时还能做什么。我已经读到这可能是特定版本的 Express 的一个潜在问题,但我已经尝试降级/升级,但这并没有改变任何东西。

有了一些断点,看起来我在 PassportConfig.js 中的新 localStrategy 从未被调用,但我不完全确定这是否是我的错误?真的很感激这里的一些指示。

app.js

require("./config/config");
require("./models/db");
require("./config/passportConfig");

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const passport = require("passport");

// router
var rtsIndex = require("./routes/index.router");

var app = express();

// middleware config
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.use(passport.initialize());
app.use(passport.session());
app.use("/api", rtsIndex);

我的 PassportConfig.js:

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const mongoose = require("mongoose");

var User = mongoose.model("User");

passport.use(
  new LocalStrategy({ usernameField: "email" }, (username, password, done) => {
    User.findOne({ email: username }, (err, user) => {
      if (err) return done(err);
      // if user is unknown
      else if (!user)
        return done(null, false, {
          message: "That email address has not been registered"
        });
      // or if password is wrong
      else if (!user.verifyPassword(password))
        return done(null, false, { message: "Wrong password" });
      // successful authentication
      else return done(null, user);
    });
  })
);

我的基本用户注册/登录系统控制器:

const mongoose = require("mongoose");
const passport = require("passport");
const _ = require("lodash");

User = require("../models/user.model");

// snipped some registration code for brevity

module.exports.authenticate = (req, res, next) => {
  console.log(req.body);
  // call for passport authentication
  // executed passport.use from passportConfig
  passport.authenticate("local", (err, user, info) => {
    // Error from passport middleware
    if (err) return res.status(400).json(err);
    // user is registered if there is a value in 'user'
    else if (user) return res.status(200).json({ token: user.generateJwt() });
    // user unkown or wrong password
    else return res.status(401).json(info);
  })(req, res);
};

编辑:也添加了我的用户模型定义:

const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");

var userSchema = new mongoose.Schema({
  fullName: {
    type: String,
    required: "Full name cannot be empty"
  },
  email: {
    type: String,
    required: "Email cannot be empty",
    unique: true
  },
  password: {
    type: String,
    required: "Password cannot be empty",
    minlength: [4, "Password must be at least 4 characters long"]
  },
  // Encryption/Decryption of password
  saltSecret: String
});

// Custom validation for email
userSchema.path("email").validate(val => {
  emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  return emailRegex.test(val);
}, "Invalid email");

// Events
userSchema.pre("save", function(next) {
  bcrypt.genSalt(10, (err, salt) => {
    bcrypt.hash(this.password, salt, (err, hash) => {
      this.password = hash;
      this.saltSecret = salt;
      next();
    });
  });
});

// Methods
userSchema.methods.verifyPassword = function(password) {
  // plain password, vs encrypted password,
  // called from findOne in passportConfig
  return bcrypt.compareSync(password, this.password);
};

userSchema.methods.generateJwt = function() {
  return jwt.sign({ _id: this._id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXP
  });
};

// Can pass custom name as third paramater
// Modified with a force export for debugging
module.exports = mongoose.model("User", userSchema);

最后,一些基本的路由:

const express = require("express");
const router = express.Router();

const ctrlUser = require("../controllers/user.controller");

// foreword all links with api/
router.post("/register", ctrlUser.register);
router.post("/authenticate", ctrlUser.authenticate);

// Export router for middleware so app.js can access it
module.exports = router;

对于这些问题,我尝试了以下解决方案:

由于不是正文解析器问题,我认为这可能是 usernameField 问题,但似乎也不是这样。

【问题讨论】:

    标签: node.js express authentication local


    【解决方案1】:

    我已经试用了您上面提到的代码。 而且我几乎没有做任何更改并删除了一些验证。 我在下面提到所有文件:

    passportMiddleware.js

    import passportLocal from 'passport-local';
    const localStrategy = passportLocal.Strategy;
    import userModel from '../model/userModel';
    import passport from 'passport';
    import bcrypt from 'bcrypt';
    
    passport.use(new localStrategy({
            usernameField: 'email',
        }, async (email, password, done) => {
            const user = await userModel.findOne({ "email": email });
            // console.log(user)
            if (!user) {
                return done(null, false);
            }
            try {
                if (password === user.password) {
                    return done(null, user)
                } else {
                    return done(null, false, 'password Incorrect')
                }
            } catch (error) {
                return done(error)
            }
        }));
    

    userController.js

    import userModel from '../model/userModel';
    import bcrypt from 'bcrypt';
    import passport from 'passport';
    
    exports.authenticate = (req, res, next) => {
            res.status(200).json({ messaage: 'Authenticated', data: req.user 
        });
    };
    

    userModel.js

    import mongoose from 'mongoose';
    import bcrypt from 'bcrypt';
    import jwt from 'jsonwebtoken';
    
    var userSchema = new mongoose.Schema({
                name: {
                    type: String,
                    required: true
                },
                email: {
                    type: String,
                    required: true,
                    unique: true
                },
                password: {
                    type: String,
                    required: true,
    
                }
            });
    
            // Events
            userSchema.pre("save", function (next) {
                bcrypt.genSalt(10, (err, salt) => {
                    bcrypt.hash(this.password, salt, (err, hash) => {
                        this.password = hash;
                        this.saltSecret = salt;
                        next();
                    });
                });
            });
    
            module.exports = mongoose.model("Users", userSchema);
    

    routes.js

    router.post('/authenticate', passport.authenticate('local', { session: false }), userController.authenticate);

    试试这个。先导入依赖。

    一旦您成功使用本地护照进行身份验证。您可以根据自己的标准进行更改。

    我有 ES6 格式的导入依赖项。您只需将其更改为 ES5。

    【讨论】:

    • 嘿,所以我尝试运行您提供的路线,但现在我的错误最终变成了 400 Bad Request,但感谢您的尝试,我很感激 :) 你是对的,我会移动那个注册码!
    • 嘿,我刚刚编辑了答案。试试这个。希望这对您有所帮助。
    • 感谢您花时间帮助我完成这项工作,我的人,非常感谢。不幸的是,我昨天得到了这个工作,但只是忘了更新我的问题,我的问题很奇怪,以至于我的代码格式扩展 Prettier 在我的护照配置中弄乱了对本地策略的回调,所以在对文件的方式进行了一些调整之后保存它最终正常工作。在那之后,这只是让我的 POST 请求正确填写的一个例子,因为我在我的新本地策略中覆盖了默认值。不过,我喜欢您的更新答案,再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 2017-05-25
    • 2018-04-21
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多