我有使用passport-local-mongoose的用户注册,但我的登录失败,我不知道为什么。
架构:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const modelHelper = require('../helpers/modelHelper')
const constants = require('../lib/constants')
const {getName} = require('country-list')
const passportLocalMongoose = require('passport-local-mongoose')
Schema.Types.Boolean.convertToFalse = new Set([false])
Schema.Types.Boolean.convertToTrue = new Set([true])
const User = new Schema({
title: {
type: String,
trim: true
},
firstName: {
type: String,
trim: true,
required: true
},
lastName: {
type: String,
trim: true,
required: true
},
practice: {
type: String,
trim: true
},
addressLine1: {
type: String,
trim: true,
required: true
},
addressLine2: {
type: String,
trim: true
},
city: {
type: String,
trim: true,
required: true
},
state: {
type: String,
trim: true
},
postcode: {
type: String,
trim: true,
uppercase: true,
required: true
},
jobTitle: {
type: String,
trim: true,
required: true
},
country: {
type: String,
trim: true,
uppercase: true,
required: true,
validate: modelHelper.mustBeCountryCode
},
locale: {
type: String,
trim: true,
required: true,
match: /[a-z]{2}-[A-Z]{2}/,
validate: modelHelper.mustBeLocaleCode
},
userRole: {
type: String,
trim: true,
required: true,
enum: [
constants.USER,
constants.ADMINISTRATOR
]
},
termsAccepted: {
type: Boolean,
required: true,
validate: modelHelper.mustBeTrue
},
consentOptIn: {
type: Boolean
},
legacyUserId: {
type: Number
}
}, {
timestamps: true
})
User.plugin(passportLocalMongoose)
/**
* Getter method concatenates first and last names
*
* @returns {string}
*/
const getFullName = () => `${this.firstName} ${this.lastName}`
User.virtual('fullName').get(getFullName)
module.exports = mongoose.model('User', User)
应用:
require('dotenv').config()
require('./db')
const express = require('express')
const cors = require('cors')
const helmet = require('helmet')
const morgan = require('morgan')
const app = express()
const router = require('./routes')
const cookieParser = require('cookie-parser')
const passport = require('passport')
const User = require('./models/User')
const responseHelper = require('./helpers/responseHelper')
// load middleware
app.use(helmet())
app.use(morgan('tiny'))
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.use(cookieParser())
app.use(passport.initialize())
// prefix all routes with /v1
app.use('/v1', router)
// configure passport
passport.use(User.createStrategy())
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())
// listen
app.listen(process.env.PORT, () =>
console.log(`Listening on port ${process.env.PORT}.`)
)
// 404 unrecognised routes
app.use((req, res, next) => responseHelper.handleNotFoundError(res))
和控制器:
const User = require('../models/User')
const { populateModel } = require('../helpers/modelHelper')
const responseHelper = require('../helpers/responseHelper')
const { body, validationResult } = require('express-validator')
const passport = require('passport')
const jwt = require('jsonwebtoken')
const JwtStrategy = require('passport-jwt').Strategy
const ExtractJwt = require('passport-jwt').ExtractJwt
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.AUTH_SECRET
}
module.exports.register = [
body('username', 'A valid Email is required').isEmail().custom(value => {
return User.findOne({ username: value }).then(user => {
if (user !== null) {
return Promise.reject('Email already in use')
}
})
}),
(req, res) =>{
const user = new User(),
fillable = [
'title',
'firstName',
'lastName',
'practice',
'addressLine1',
'addressLine2',
'city',
'state',
'postcode',
'jobTitle',
'country',
'locale',
'userRole',
'termsAccepted',
'consentOptIn',
'username',
'password',
'legacyUserId'
],
errors = validationResult(req)
if ( ! errors.isEmpty()) return responseHelper.handleValidationError(res, errors)
populateModel(user, fillable, req.body)
User.register(user, req.body.password, (err) => err ? responseHelper.handleOperationError(res, err) : responseHelper.handleSuccess(res, {user: user, token: ''}))
}
]
module.exports.login = [
body('username', 'Email is required').not().isEmpty().isEmail(),
body('password', 'Password is required').not().isEmpty(),
(req, res) => {
const errors = validationResult(req)
if ( ! errors.isEmpty()) return responseHelper.handleValidationError(res, errors)
passport.authenticate('local', {}, (err, user, info) => {
if (err) return responseHelper.handleOperationError(res, err)
if ( ! user) return responseHelper.handleAuthError(res, info)
req.logIn(user, (err) => {
if (err) return responseHelper.handleAuthError(res, err)
const token = jwt.sign({ _id: user._id }, process.env.AUTH_SECRET, { expiresIn: 1800 })
return res.json({
message: "Authentication successful.",
user: user,
token: token
})
})
})(req, res)
}
]
这是一个 API 应用程序,因此我将回调传递给 passport.authenticate()
,但出现 IncorrectPasswordError
错误,并且我可以看到我使用的登录密码与我用于登录的密码相同注册。
据我所知,~/node_modules/passport-local-mongoose/lib/authenticate.js
中的 pbkdf2() 方法在此检查中失败:
if (scmp(hashBuffer, Buffer.from(user.get(options.hashField), options.encoding))) {
// ...
} else {
// i am here
}
我是否在配置中遗漏了什么或错误地调用了 register
或 authenticate
方法?