سلام و درود
استاد امیدوارم حالتون خوب باشه
من به یه مشکلی در مورد متد hash و compare برخوردم
از نظر خودم که ارور منطقی نیستش ولی حالا به هر حال بهش برخوردم
من بکند رو با nodejs و فرانت رو با reactjs برنامه نویسی کردم
من موقعی که کاربر ثبت نام میکنه پسوردش رو هش میکنم
userSchema.pre("save", async function (next) {
try {
if (this.isModified("password")) {
this.password = await hashPassword(this.password);
}
next();
} catch (err) {
next(err);
}
});
و تا اینجا عادیه
وقتی لاگین هم میکنم کار میکنه
module.exports = async (req, res) => {
const errors = [];
try {
const { username, password, rememberMe } = req.body;
let user = await User.findOne({ username });
if (user == null) {
user = await User.findOne({ email: username });
if (!user) {
errors.push({
name: "email",
message: "کاربر با این نام کاربری یا ایمیل در سایت موجود نمیباشد!",
});
return res
.status(400)
.json({ status: "error", statusCode: 400, errors });
}
}
console.log(typeof password)
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) {
errors.push({
name: "password",
message: err.message,
});
return res
.status(400)
.json({ status: "error", statusCode: 400, errors });
}
if (isMatch) {
let jwtSecretKey = process.env.JWT_SECRET_KEY;
let data = {
time: Date(),
userId: user.id,
};
const token = jwt.sign(data, jwtSecretKey, {
expiresIn: `${rememberMe ? "10d" : "2h"}`,
});
res.status(200).json({
status: "success",
statusCode: 200,
errors: null,
user: { ...user._doc, token, password: undefined },
});
} else {
errors.push({
name: "password",
message: "نام کاربری/ایمیل یا کلمه عبور اشتباه است!",
});
return res
.status(400)
.json({ status: "error", statusCode: 400, errors });
}
});
} catch (err) {
console.log(err);
error.inner.forEach((e) => {
errors.push({
name: e.path,
message: e.message,
});
});
return res.status(400).json({ status: "error", statusCode: 400, errors });
}
};
تا اینجا همه چی اکیه
من یه بخش دیگه هم برای تغییر کلمه عبور دارم که اونجا کلمه عبور قبلی و جدید رو از کاربر میگیرم
exports.changePassword = async (req, res) => {
const errors = [];
try {
const jwtValidation = tokenValidation(req.headers["x-access-token"]);
if (jwtValidation.userId !== null) {
const user = await User.findById(jwtValidation.userId);
if (user) {
if (
req.body.password &&
req.body.newPassword &&
req.body.newPasswordRepeat
) {
if (req.body.newPassword == req.body.newPasswordRepeat) {
console.log(typeof req.body.newPassword);
const hashedPassword = await hashPassword(req.body.newPassword) //! Hash
console.log("req.body.password", req.body);
console.log("user.password", user.password);
bcrypt.compare(req.body.password, user.password, (err, isMatch) => {
if (err) {
console.log(err);
return res.status(400).json({
status: "error",
statusCode: 400,
errors: [
{
name: "bcrypt",
message: "خطایی از سمت سرور رخ داده است!",
},
],
});
}
if (isMatch) {
if (hashedPassword) {
console.log("hashedPassword", hashedPassword);
user.password = hashedPassword;
user.save();
return res.status(200).json({
status: "success",
statusCode: 200,
errors: null,
});
} else {
console.log(err);
return res.status(400).json({
status: "error",
statusCode: 400,
errors: [
{
name: "bcrypt",
message: "خطایی از سمت سرور رخ داده است!",
},
],
});
}
} else {
return res.status(400).json({
status: "error",
statusCode: 400,
errors: [
{
name: "password",
message: "کلمه عبور ارسالی با کلمه عبور اصلی یکسان نیست!",
},
],
});
}
});
} else {
return res.status(400).json({
status: "error",
statusCode: 400,
errors: [
{
name: "newPassword",
message: "کلمه عبور جدید و تکرار آن یکسان نیستند!",
},
],
});
}
}
} else {
return res.status(400).json({
status: "error",
statusCode: 400,
errors: [{ name: "user", message: "کاربر مورد نظر یافت نشد!" }],
});
}
} else {
return res.status(400).json({
status: "error",
statusCode: 400,
errors: jwtValidation.errors,
});
}
} catch (err) {
console.log(err);
err.inner.forEach((e) => {
errors.push({
name: e.path,
message: e.message,
});
});
return res.status(400).json({ status: "error", statusCode: 400, errors });
}
};
و اینجا هم compare کار میکنه!
ولی وقتی پسورد رو عوض میکنم و اون hash جدید که اومده رو توی دیتابیس ذخیره میکنم
و اینبار که میخواد کاربر لاگین کنه با پسورد جدید نمیشه :)
یعنی ارور میده که پسورد match نیستش
منظورم اینه که اون پسورد جدید رو میگه استباهه و درست campare نمیکنه درحالی که هردوشون با یه salt ساخته میشن و کلا هم موقع ساخت حساب و هم موقع تغییر پسورد اون پسورد به یک شکل hash میشه ولی نمیدونم چره موقع compare اون پسورد جدید رو میگه اشتباهه
اینم کدای ساخت hash هستش:
const bcrypt = require("bcryptjs");
module.exports = async (password) => {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
return hashedPassword;
};
خواهشا کمک کنین یک هفتس پروژم بخواطر این خوابیده
سلام دوست من
خیلی عذرخواهی میکنم که دیر دارم جواب میدم به طور عجیبی ایمیل این سوال رو ندیدم
مشکل رو برطرف کردی یا هنوزم این مشکل رو داری ؟
خواهش میکنم استاد
بعله هنوز همین مشکل رو دارم
3 4 روز درگیرش بودم
به نتیجه ای هم نرسیدم
سلام خوب هستید.
اگه در قسمت رجیستر با دوره پیش رفتید , ما برای هش کردن پسورد از قابلیت pre که برای mongoose هست استفاده کردیم. اونجا قبل از اینکه user ساخته بشه پسورد هش میشه. شاید مشکل اونجا باشه و دوبار رمز هش میشه و تغییر میکنه.
امیدوارم مشکل حل بشه.
سلام دوست عزیز
نه فکر کنم سوال رو اشتباه متوجه شده باشید
اولین تکه کدی که گذاشتم اگه دقت کنین میبینین که منم از قابلی pre قبل از ذخیره کردن کاربر استفاده کردم
از اونجایی که ما از pre استفاده کردیم نیازی نیست که دستی هش کنی بعد از تغییر رمز
مشکل از همین باید باشه چون ۲ بار داره هش میشه و به همین خاطر مشکل پیش میاد
مثل رمز اول داده شده که خودت دستی هش کردی و زمانی هم که ذخیره میکنی توسط متد نوشته شده درون pre هم کلمه عبور هش شده دستی دوباره هش میشه پس متفاوت خواهد بود
در زمان تغییر رمز عبور فقط رمز جدید رو ذخیره کن خودش هش میشه اتوماتیک
مشکلت باید برطرف بشه
آها بعله استاد کاملا درسته
پسورد دوبار هش میشد
یک بار وقتی من دستی هش میکردم
یکبار هم قبل از سیو
ممنون از شما ❤️