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

Node.js用户注册时邮箱查重功能实现及代码优化咨询

Node.js注册时邮箱重复验证实现及代码优化

一、邮箱已存在验证的实现步骤

在用户注册提交时,先查询数据库中是否存在相同邮箱,再执行插入操作:

  1. 在saveRegister方法中,先执行查询邮箱是否存在的SQL语句
  2. 根据查询结果判断:
    • 若邮箱已存在,通过flash返回错误提示并跳转回注册页
    • 若邮箱不存在,再执行用户数据插入操作

二、现有代码的优化点

  • 错误处理不严谨:直接throw err会导致服务器崩溃,需改为捕获错误并返回用户友好提示
  • 数据库连接释放时机错误:connection.release()放在回调外会导致连接提前释放,需移至查询回调内部
  • 硬编码URL:http://localhost:5050/应放在配置文件中,避免硬编码
  • 表单验证薄弱:仅判断字段非空,缺少邮箱格式校验
  • 密码哈希方式建议:建议使用专门的加密库(如bcrypt)而非数据库函数,更安全且便于维护
  • 视图渲染错误:formRegister中渲染login视图,但注释说明是register.ejs,存在逻辑矛盾
  • 变量命名不规范:pass应改为password,与字段名保持一致

三、修改后的完整代码

router_register.js(逻辑无问题,保留原结构)

//router_register.js
// 定义express路由
const router = require('express').Router();
// 引入register控制器
const registerController = require('../controllers').register;
// 引入登录状态验证中间件
const verifyUser = require('../configs/verify');

// 显示注册表单路由,仅未登录用户可访问
router.get('/', verifyUser.isLogout, registerController.formRegister);
// 处理注册提交路由,仅未登录用户可访问
router.post('/save', verifyUser.isLogout, registerController.saveRegister);

module.exports = router;

controller_register.js(添加邮箱验证+优化后)

//controller_register
const config = require('../configs/database');
const mysql = require('mysql');
const pool = mysql.createPool(config);
// 可选:安装bcrypt后替换SHA2,执行npm install bcrypt
// const bcrypt = require('bcrypt');
// const saltRounds = 10;

pool.on('error', (err)=> {
  console.error('数据库连接池错误:', err);
});

module.exports = {
  formRegister(req, res) {
    // 修正视图渲染,改为register.ejs
    res.render("register", {
      // 建议从配置文件读取baseURL,或用环境变量
      url: process.env.BASE_URL || 'http://localhost:5050/',
      // 传递flash消息到视图
      messages: req.flash()
    });
  },
  saveRegister(req, res) {
    let username = req.body.username;
    let email = req.body.email;
    let password = req.body.password; // 修正变量名,与表单字段一致

    // 增强表单验证:邮箱格式校验+字段非空
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!username || !email || !password || !emailRegex.test(email)) {
      req.flash('color', 'danger');
      req.flash('status', '错误..');
      req.flash('message', '请填写完整信息或输入正确格式的邮箱');
      return res.redirect('/register'); // 跳转回注册页而非登录页
    }

    pool.getConnection(function(err, connection) {
      if (err) {
        console.error('获取数据库连接失败:', err);
        req.flash('color', 'danger');
        req.flash('status', '错误..');
        req.flash('message', '服务器连接失败,请稍后重试');
        return res.redirect('/register');
      }

      // 查询邮箱是否已存在
      connection.query(
        `SELECT user_email FROM table_user WHERE user_email = ?`, [email], function (error, results) {
          if (error) {
            console.error('查询邮箱失败:', error);
            req.flash('color', 'danger');
            req.flash('message', '验证邮箱失败,请稍后重试');
            connection.release(); // 释放连接
            return res.redirect('/register');
          }

          // 邮箱已存在的情况
          if (results.length > 0) {
            req.flash('color', 'danger');
            req.flash('status', '提示..');
            req.flash('message', '该邮箱已被注册,请更换邮箱');
            connection.release();
            return res.redirect('/register');
          }

          // 邮箱不存在,执行插入操作
          // 可选:使用bcrypt哈希密码(推荐)
          // bcrypt.hash(password, saltRounds, function(bcryptErr, hash) {
          //   if (bcryptErr) throw bcryptErr;
          //   connection.query(
          //     `INSERT INTO table_user (user_name, user_email, user_password) VALUES (?,?,?)`, 
          //     [username, email, hash], function (insertError, insertResults) {
          //       // 插入逻辑处理
          //     }
          //   )
          // })
          
          // 原有SHA2哈希方式(建议替换为bcrypt)
          connection.query(
            `INSERT INTO table_user (user_name, user_email, user_password) VALUES (?,?,SHA2(?,512))`, 
            [username, email, password], function (insertError, insertResults) {
              connection.release(); // 插入完成后释放连接
              if (insertError) {
                console.error('注册插入失败:', insertError);
                req.flash('color', 'danger');
                req.flash('message', '注册失败,请稍后重试');
                return res.redirect('/register');
              }
              req.flash('color', 'success');
              req.flash('status', '成功..');
              req.flash('message', '注册成功,请登录');
              res.redirect('/login');
            }
          );
        }
      );
    })
  }
}

补充说明

  • 若使用bcrypt,需先执行npm install bcrypt安装依赖,替换原有数据库哈希逻辑
  • 建议在项目根目录创建.env文件存储BASE_URL等配置,使用dotenv库读取
  • 视图层(register.ejs)需添加flash消息的展示逻辑,方便用户看到提示

内容的提问来源于stack exchange,提问作者Mighty 27_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 06:06:19