You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:35:54