Logo
Section 1 / 7

使用 bcrypt 进行密码哈希

学习在将用户凭据存储到数据库之前,使用 bcrypt 对密码进行哈希处理,以保护用户凭证安全。

导入

使用 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 命令测试接口响应。

  1. 注册成功:请求注册一个具有有效用户名和密码的新用户。

    1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1用户注册成功。
  2. 登录成功:使用已注册用户的凭据进行登录请求。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1登录成功。
  3. 使用无效凭据登录:使用错误密码尝试登录。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'

    预期响应:

    1用户名或密码无效。

点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。

  1. 注册成功: 请求注册一个具有有效用户名和密码的新用户。

    1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1用户注册成功。
  2. 登录成功: 使用已注册用户的凭据发起登录请求。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1登录成功。
  3. 使用无效凭据登录: 使用错误密码尝试登录。

    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 命令测试接口响应。

  1. 用户注册:请求注册一个具有唯一用户名的新用户。

    1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1用户注册成功。
  2. 用户登录(成功):使用已注册用户的正确凭据进行登录请求。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1登录成功。
  3. 用户登录(凭据无效):使用错误密码尝试登录。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "wrongpassword"}'

    预期响应:

    1用户名或密码无效。

点击“运行”按钮启动服务器,然后点击“+”标签页打开一个新终端。使用以下 curl 命令测试接口响应。

  1. 用户注册: 请求注册一个具有唯一用户名的新用户。

    1curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1用户注册成功。
  2. 用户登录(成功): 使用已注册用户的正确凭据进行登录请求。

    1curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username": "johndoe", "password": "secret123"}'

    预期响应:

    1登录成功。
  3. 用户登录(凭据无效): 使用错误密码尝试登录。

    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 状态码及通用错误信息。

构建 RESTful API 并集成数据库

JWT 认证:生成与签发令牌