使用bcrypt加密密码时报data must be a string or Buffer错误如何解决
问题根因
该报错本质是bcrypt.hash()方法接收的参数不符合要求,具体有2个常见触发场景:
- Postman提交的请求体里
password字段为空、字段名拼写错误,或是请求头未正确设置Content-Type: application/json,导致req.body.password拿到的是undefined/非字符串类型的值,不符合bcrypt要求的第一个参数必须是字符串/Buffer的规则 - 代码本身缺少参数校验逻辑,也未确认
bcrypt.genSalt()是否正确生成了有效盐值
修复步骤
- 第一步:校验Postman请求配置
确认请求方法为POST,请求头已添加Content-Type: application/json,请求体JSON格式合法,password字段名拼写正确且值不为空 - 第二步:修改代码补全逻辑疏漏
你现有代码中插入用户的pool.query操作未加await,也没有对请求参数做合法性校验,完整修复后的代码如下:
const router = require('express').Router(); const pool = require('../utils/db') const bcrypt = require('bcrypt') const jwt = require('jsonwebtoken') router.post("/register", async (req, res) => { try { const { username, email, password } = req.body // 新增参数非空校验 if (!username || !email || !password) { return res.status(400).send('必填参数不能为空') } // 强制转换password为字符串类型,避免类型不匹配 const pwdStr = String(password) const user = await pool.query('select * from users where email = $1', [email]) if (user.rows.length !== 0) { return res.status(401).send('user already exists') } const saltRounds = 10; // 可直接传盐轮数到hash方法,省去单独生成salt的步骤 const bcryptPassword = await bcrypt.hash(pwdStr, saltRounds) // 新增await,确保用户插入成功再生成jwt,添加returning返回插入的用户数据 const newUser = await pool.query('insert into users(username,password,email) values ($1,$2,$3) returning *', [username, bcryptPassword, email]) // 用新插入的用户信息生成jwt,避免使用之前查询的旧user对象 jwt.sign({user: newUser.rows[0]}, 'secretkey', { expiresIn: '30s' }, (err, token) => { if(err) { return res.status(500).send('生成token失败') } res.json({ token }); }); } catch (err) { console.log(err) res.status(500).send('服务器错误') } })
- 额外优化:你可以直接把盐轮数作为第二个参数传入
bcrypt.hash,不需要单独调用bcrypt.genSalt生成盐,bcrypt内部会自动完成盐的生成逻辑,代码更简洁。
内容的提问来源于stack exchange,提问作者Belahrach Anas
相关产品推荐
相关产品推荐

