
在现代Web应用中,用户密码的安全性至关重要。直接存储明文密码是极其危险的做法,一旦数据库泄露,所有用户账户都将面临风险。为了解决这一问题,我们通常采用密码哈希(Hashing)技术。密码哈希是将原始密码通过单向加密算法转换为一串固定长度的、不可逆的字符串。每次用户注册时,我们存储的是密码的哈希值而非明文;用户登录时,则将用户输入的密码进行哈希,然后与数据库中存储的哈希值进行比对。
bcrypt是一种流行的密码哈希算法,以其计算成本高(抗暴力破解)和内置盐值(Salt)而闻名。盐值是一个随机字符串,与密码一起进行哈希,确保即使两个用户设置了相同的密码,其哈希值也不同,从而有效抵御彩虹表攻击。
在Node.js生态中,有两个主要的库用于实现bcrypt算法:
考虑到兼容性和部署的便捷性,我们强烈推荐在Node.js应用中使用bcryptjs进行密码处理。
首先,需要在你的项目中安装bcryptjs库:
npm install bcryptjs
在用户注册时,我们需要获取用户提供的明文密码,对其进行加盐哈希处理,然后将哈希后的密码存储到数据库中。
const express = require('express');
const bcrypt = require('bcryptjs'); // 引入 bcryptjs
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const cors = require('cors');
const secretKey = 'your-secret-key'; // 替换为你的JWT密钥
const app = express();
app.use(cors());
app.use(express.json());
// MongoDB connection URI
const uri = 'mongodb://localhost:27017/final-year-project';
// Connect to the MongoDB database
mongoose
.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('Connected to the database');
app.listen(3000);
console.log('app connected on port 3000');
})
.catch((error) => {
console.error('Failed to connect to the database:', error);
});
// Define the user schema
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true, unique: true },
role: { type: String, required: true },
password: { type: String, required: true },
}, { collection: 'users' });
// Define the user model
const User = mongoose.model('User', userSchema);
class AuthResponseData {
constructor(user) {
this.user = user;
}
}
// Signup endpoint
app.post('/signup', async (req, res) => {
try {
const { firstName, lastName, email, role, password } = req.body;
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({ message: 'Email already exists' });
}
let plainTextPassword = password;
if (!plainTextPassword) {
plainTextPassword = 'defaultPassword123'; // 建议在实际应用中避免设置默认密码
}
// 使用 bcryptjs 进行密码哈希
// genSaltSync(10) 生成盐值,10是盐值轮数,影响哈希强度和计算时间
const hashedPassword = await bcrypt.hash(plainTextPassword, 10);
const newUser = new User({
firstName,
lastName,
email,
role,
password: hashedPassword, // 存储哈希后的密码
});
await newUser.save();
const token = jwt.sign({ email: newUser.email }, secretKey, { expiresIn: '1h' }); // 设置JWT过期时间
const expirationDate = new Date().getTime() + 3600000;
const user = {
firstName: newUser.firstName,
lastName: newUser.lastName,
email: newUser.email,
role: newUser.role,
id: newUser._id,
_token: token,
_tokenExpirationDate: expirationDate,
};
const authResponse = new AuthResponseData(user);
res.status(201).json(authResponse);
} catch (error) {
console.error('Signup error:', error);
res.status(500).json({ message: 'Internal server error' });
}
});代码解析:
在用户登录时,我们需要从数据库中获取存储的哈希密码,然后将用户输入的明文密码与这个哈希密码进行比对。
// Login endpoint
app.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
// 1. 查找用户
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: 'Invalid email or password' });
}
// 2. 比对密码
// bcrypt.compare(plainTextPassword, hashedPasswordFromDb)
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ message: 'Invalid email or password' });
}
// 3. 生成JWT并返回认证信息
const token = jwt.sign({ email: user.email }, secretKey, { expiresIn: '1h' });
const expirationDate = new Date().getTime() + 3600000;
const loggedInUser = {
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
role: user.role,
id: user._id,
_token: token,
_tokenExpirationDate: expirationDate,
};
const authResponse = new AuthResponseData(loggedInUser);
res.status(200).json(authResponse);
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ message: 'Internal server error' });
}
});代码解析:
通过使用bcryptjs库,我们能够安全、可靠地在Node.js应用中实现密码的哈希存储与验证。bcryptjs作为纯JavaScript实现,有效规避了原生bcrypt库可能带来的兼容性问题,为开发者提供了一个稳定且易于集成的解决方案。遵循上述教程和最佳实践,可以显著提升Web应用的用户认证安全性。
以上就是深入理解Node.js中bcryptjs进行密码哈希与验证的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号