使用Knex.js与PostgreSQL实现密码重置时遇网络错误的求助
问题修复与优化方案
一、网络错误直接原因
你遇到的NetworkError是因为后端未定义/forgot-user的POST路由,前端发送请求后找不到对应接口;同时前端忘记密码的请求未携带用户邮箱,后端无法定位要更新的用户。
二、基础修复步骤
1. 后端(server.js)添加/forgot-user路由
在登录路由后新增如下代码,处理密码更新逻辑:
app.post('/forgot-user', (req, res) => { const { email, password } = req.body; // 校验字段是否为空 if (!email.length || !password.length) { return res.json('fill all the fields'); } // 根据邮箱更新用户密码 db('users') .where({ email: email }) .update({ password: password }) .returning(['name', 'email']) .then(data => { if (data.length) { res.json(data[0]); // 更新成功返回用户信息 } else { res.json('email does not exist'); // 邮箱未注册 } }) .catch(err => { res.json('error updating password'); }); });
2. 前端(form.js)修正忘记密码请求
在忘记密码的分支中,添加用户输入的邮箱字段,并补全错误捕获:
//forgot password else if(name==null || password==null){ submitBtn.addEventListener('click',()=>{ fetch('/forgot-user',{ method : 'post', headers:new Headers({'Content-Type':'application/json'}), body:JSON.stringify({ email: reemail.value, // 新增邮箱字段,用于定位用户 password: repassword.value }) }) .then(res=>res.json()) .then(data=>{ validateData(data); }) .catch(err => { alertBox('network error, please try again'); // 捕获网络异常 }) }) }
三、安全优化:密码哈希存储(必做)
当前代码明文存储密码存在严重安全隐患,使用bcrypt对密码进行哈希处理:
1. 安装依赖
npm install bcrypt
2. 修改后端核心逻辑
更新注册、登录、密码重置的代码,替换为哈希验证逻辑:
const bcrypt = require('bcrypt'); const saltRounds = 10; // 哈希迭代强度,数值越高越安全 // 注册:哈希后存储密码 app.post('/register-user',(req,res)=>{ const {name, email, password } = req.body; if(!name.length || !email.length || !password.length){ return res.json('fill all the fields'); } bcrypt.hash(password, saltRounds, (err, hash) => { if (err) return res.json('error creating user'); db("users").insert({ name:name, email:email, password:hash // 存储哈希值而非明文 }) .returning(["name", "email"]) .then(data=>{ res.json(data[0]) }) .catch(err =>{ if(err.detail.includes('already exists')){ res.json('email already exists'); } else { res.json('error creating user'); } }); }) }) // 登录:验证哈希密码 app.post('/login-user',(req,res)=>{ const{email, password}=req.body; db.select('name','email','password') .from('users') .where({ email:email }) .then(data=>{ if(data.length){ bcrypt.compare(password, data[0].password, (err, result) => { if (result) { // 密码匹配,返回用户信息(绝不返回密码) res.json({ name: data[0].name, email: data[0].email }); } else { res.json('email or password is incorrect'); } }) }else{ res.json('email or password is incorrect'); } }) .catch(err => { res.json('error logging in'); }) }) // 密码重置:哈希后更新密码 app.post('/forgot-user', (req, res) => { const { email, password } = req.body; if (!email.length || !password.length) { return res.json('fill all the fields'); } bcrypt.hash(password, saltRounds, (err, hash) => { if (err) return res.json('error updating password'); db('users') .where({ email: email }) .update({ password: hash }) .returning(['name', 'email']) .then(data => { if (data.length) { res.json(data[0]); } else { res.json('email does not exist'); } }) .catch(err => { res.json('error updating password'); }); }) })
四、额外优化建议
- 前端
validateData函数中,不要将密码存入sessionStorage,仅存储用户名和邮箱即可 - 所有Promise请求添加
catch处理,避免未捕获的异常 - 后端路由中使用
return终止后续代码执行,防止重复响应
内容的提问来源于stack exchange,提问作者Zoro
相关产品推荐
相关产品推荐

