node.js - Mongoose Schema.method() 不起作用,并显示错误消息
问题描述
我正在从用户那里输入密码并使用密码加密密码,然后保存到数据库中。这是我的代码,这里我将加密的密码存储到来自 userSchema 的 encry_password 属性中。但是,这给了我“this.securePassword”不是函数的错误。
const mongoose = require("mongoose");
const crypto = require("crypto");
const { v1: uuidv1 } = require("uuid");
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
maxlength: 32,
trim: true,
},
lastname: {
type: String,
maxlength: 32,
trim: true,
},
email: {
type: String,
trim: true,
required: true,
unique: true,
},
usrinfo: {
type: String,
trim: true,
},
encry_password: {
type: String,
required: true
},
salt: String,
role: {
type: Number,
default: 0,
},
purchases: {
type: Array,
default: [],
},
}, { timestamps: true });
userSchema.virtual("password")
.set((password) => {
this._password = password;
this.salt = uuidv1();
this.encry_password = securePassword(password, uuidv1());
console.log(this.encry_password);
})
.get(() => {
return this._password;
});
// const authenticate = function (plainPassword, encry_password) {
// return securePassword(plainPassword) === encry_password;
// };
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
} catch (error) {
return "";
}
};
module.exports = mongoose.model("User", userSchema);
用户注册路径
exports.signup = (req, res) => {
console.log(req.body);
const user = new User(req.body);
user.save((err, user) => {
if (err) {
console.log(err);
res.status(400).json({
err: "Note able to save the user in database"
});
} else {
res.json(user);
}
});
};
解决方案
首先,在这种情况下你不应该使用virtual
Virtuals 是您可以获取和设置但不会持久保存到 MongoDB 的文档属性。getter 可用于格式化或组合字段,而 setter 可用于将单个值分解为多个值以进行存储。
但是在范围内virtual
,this
不能访问方法,你不能像你的方式那样访问方法,这是mongoose中方法使用的一个例子
const Animal = mongoose.model('Animal', animalSchema);
const dog = new Animal({ type: 'dog' });
dog.findSimilarTypes((err, dogs) => {
console.log(dogs); // woof
});
您可以检查方法文档:
如果您只想以securePassword
您的方式访问,您可以喜欢这个并完全删除方法 mongoose,因为这不是使用的地方method
:
UserSchema.virtual("password")
.set((password) => {
this._password = password;
this.salt = uuidv1();
console.log("This is running");
this.encry_password = securePassword(password, this.salt);
console.log(encry_password);
})
.get(() => {
return this._password;
});
const authenticate = function (plainPassword, encry_password) {
return securePassword(plainPassword) === encry_password;
};
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto
.createHmac("sha256", salt)
.update(plainPassword)
.digest("hex");
} catch (error) {
return "";
}
};
如果你想创建authenticate service
,改变你的方式,不要使用 virtual 作为密码和使用pre save
在将有关用户的信息保存在数据库中之前,将完成此任务检查预文档
userSchema.pre("save", async function (next) {
try {
this.password = securePassword (plainPassword, salt);
} catch (error) {
console.log(error);
}
});
创建哈希密码后保存如下信息:
const userSchema = new mongoose.Schema({
.
.
.
password: { //convert encry_password to password
type: String,
}
.
.
.
}, { timestamps: true });
//every time want to user save this method called
userSchema.pre('save', function (next) {
this.salt = uuidv1()
this.password = securePassword(this.password, this.salt)
next()
})
//for have a clean routes, you can create a static methods
userSchema.statics.Create = async (data) => {
let model = new User(data);
let resUser = await model.save(); //save your user
return resUser;
};
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
} catch (error) {
return "";
}
};
let User = mongoose.model("User", userSchema)
module.exports = {User};
像这样更改控制器:
let {User} = require("./path of user schema")
exports.signup = async (req, res) => {
try {
console.log(req.body);
const user = await User.create(req.body); //create a user
res.json(user);
} catch (error) {
console.log(err);
res.status(400).json({
err: "Note able to save the user in database",
});
}
};
注意:在 req.body 中,密码字段的名称应该是password
推荐阅读
- c# - 如何在 WPF 中使用 Windows 多媒体 API (winmm.dll) 播放波形文件?
- python - 在 Python 中展平嵌套的 JSON API 字典
- apache-spark - 安装 spark 并配置它
- pdf - 如何在 PDF 中设置子字符串的样式(在 Adobe Acrobat 中)?
- c# - 如何在文档末尾插入一页?
- swift - 当用户单击正确答案时,如何使 quizView 以绿色 onTapGesture 显示
- html - 调整浏览器窗口大小时停止导航栏移动
- powershell - Powershell删除除一个以外的所有文件夹
- php - 使用 phpspreadsheet 进行斑马剥离
- c# - C# - 使用任意委托类型的表达式树创建 lambda 函数