我目前正在 NextJS 中使用 bcrypt 来哈希和比较用户密码的登录/注册功能。我可以使用散列密码注册用户,但是当尝试使用
bcrypt.compare()
登录时,比较总是返回 false,即使输入的密码与散列密码匹配。
问题出在这一行:
const isPasswordMatched = await bcrypt.compare(password, user.password);
,其中compare()
方法用于将输入的密码与散列密码进行比较。尽管实现了该方法,但它没有按预期工作。
api/auth/[...nextauth].ts
用于登录const authOptions: NextAuthOptions = {
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
async authorize(credentials, req) {
await connectDB();
const { email, password }: Icredential = credentials;
// Find user by email
const user = await User.findOne({ email: email });
if (user === null) {
throw new Error('Cannot find user');
}
// Check if password from input matches with the one from db
// This is the line of the concern
const isPasswordMatched = await bcrypt.compare(password, user.password);
console.log(`Comparing ${password} to ${user.password}`);
console.log("match ?", isPasswordMatched);
// Throw error when it doesn't
if (!isPasswordMatched)
// if (password !== '123')
{
throw new Error('Invalid email or password');
}
// Return authorized user
return user;
},
credentials: undefined
}),
],
};
export default NextAuth(authOptions);
const registerHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === "POST") {
try {
const { user: _regiUser } = req.body;
console.log(_regiUser)
//Check if user exists
await connectDB()
const existingUser = await User.findOne({ email: _regiUser.email }).exec();
console.log("existingUser", existingUser);
//Throw error when email is already in use
if (existingUser) {
throw new Error("Email already used");
}
//Password encrypted
const hashedPassword: string = await bcrypt.hashSync( _regiUser.password, 10 );
console.log("_regiUser.password", _regiUser.password, hashedPassword)
console.log(hashedPassword)
//Replace text password with encrypted password
_regiUser.password = hashedPassword;
console.log(_regiUser)
//Add user on database
await User.create(_regiUser)
res.end()
} catch (e: any) {
console.log(e.message)
}
}
};
export default registerHandler;
您正在使用
hashSync()
方法(不是异步)创建密码哈希,但尝试在登录时运行异步 .compare()
方法。查看示例.
为了比较,您应该使用:
bcrypt.compareSync(myPlaintextPassword, hash);
否则,我建议使用 async/await
bcrypt.hash
和 bcrypt.compare
方法。如果您想使用await bcrypto.compare(...)
,请使用以下方法创建哈希:
await bcrypt.hash(password, 10);
登录逻辑完全正确,但我有 错误的用户模型如下:
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
lowercase: true
},
password: {
type: String,
required: true,
lowercase: true //remove this to make it work
}
});
查看密码实体,因为我从电子邮件实体复制粘贴,我的密码配置错误。所以哈希以小写形式存储,这就是无论如何我都会出错的原因。嗯……