使用 bcrypt 进行密码哈希
学习在将用户凭据存储到数据库之前,使用 bcrypt 对密码进行哈希处理,以保护用户凭证安全。
1const express = require('express'); 2const bcrypt = require('bcrypt'); 3const app = express(); 4 5app.use(express.json()); 6 7const users = []; 8const saltRounds = 10; 9 10app.post('/register', async (req, res) => { 11 const { username, password } = req.body; 12 const hashedPassword = await bcrypt.hash(password, saltRounds); 13 users.push({ username, hashedPassword }); 14 res.send('用户注册成功。'); 15}); 16 17app.listen(3000, () => console.log('服务器运行在 3000 端口'));
No configuration found for ID: b925051051e05979509444b2ea93bcc7eef98eceb8f974045b613eabd149a7c5
点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。
-
注册成功:请求注册一个具有有效用户名和密码的新用户。
1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1用户注册成功。 -
登录成功:使用已注册用户的凭据进行登录请求。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1登录成功。 -
使用无效凭据登录:使用错误密码尝试登录。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'预期响应:
1用户名或密码无效。
点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。
-
注册成功: 请求注册一个具有有效用户名和密码的新用户。
1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1用户注册成功。 -
登录成功: 使用已注册用户的凭据发起登录请求。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1登录成功。 -
使用无效凭据登录: 使用错误密码尝试登录。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'预期响应:
1用户名或密码无效。
No configuration found for ID: 24c01c9087f4becd3b6f1dc708a32dd7475f13926af861ad2ec9aa1d94262e28
点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。
-
用户注册:请求注册一个具有唯一用户名的新用户。
1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1用户注册成功。 -
用户登录(成功):使用已注册用户的正确凭据进行登录请求。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1登录成功。 -
用户登录(凭据无效):使用错误密码尝试登录。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'预期响应:
1用户名或密码无效。
点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。
-
用户注册: 请求注册一个具有唯一用户名的新用户。
1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1用户注册成功。 -
用户登录(成功): 使用已注册用户的正确凭据进行登录请求。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'预期响应:
1登录成功。 -
用户登录(凭据无效): 使用错误密码尝试登录。
1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'预期响应:
1用户名或密码无效。
解决方案
解决方案
以下是 register 路由的解决方案:
注册路由的解决方案
1// 注册路由 2app.post('/register', async (req, res) => { 3 const { username, password } = req.body; 4 5 const existingUser = await User.findOne({ username }); 6 if (existingUser) { 7 return res.status(409).send('用户名已存在。'); 8 } 9 10 const hashedPassword = await bcrypt.hash(password, 10); 11 const user = new User({ username, hashedPassword }); 12 await user.save(); 13 14 res.status(201).send('用户注册成功。'); 15});
说明:
第 2 行: 定义一个位于
/register的 POST 路由,用于处理用户注册。第 3 行: 从请求体中提取用户名和密码。
第 5 行: 检查数据库中是否已存在相同用户名的用户。
第 6–8 行: 如果用户名已被占用,则返回
409 冲突状态码。第 10 行: 使用
bcrypt对密码进行哈希处理,盐值轮数为 10。第 11 行: 创建包含用户名和哈希密码的新用户对象。
第 12 行: 将新用户保存到数据库。
第 14 行: 注册成功后返回
201状态码。
以下是 login 路由的解决方案:
登录路由的解决方案
1// 登录路由 2app.post('/login', async (req, res) => { 3 const { username, password } = req.body; 4 5 const user = await User.findOne({ username }); 6 if (!user) { 7 return res.status(400).send('用户名或密码无效。'); 8 } 9 10 const isMatch = await bcrypt.compare(password, user.hashedPassword); 11 if (isMatch) { 12 res.send('登录成功。'); 13 } else { 14 res.status(401).send('用户名或密码无效。'); 15 } 16});
说明:
第 2 行: 定义一个位于
/login的 POST 路由,用于处理用户登录请求。第 3 行: 从请求体中提取用户名和密码。
第 5 行: 根据用户名在数据库中查找用户。
第 6–8 行: 若未找到用户,则返回
400状态码及通用错误信息。第 10 行: 使用
bcrypt.compare()方法比对提交的密码与存储的哈希值是否一致。第 11–12 行: 若密码匹配,则返回登录成功消息。
第 13–15 行: 若密码不匹配,则返回
401状态码及通用错误信息。