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

如何实现重复输入用户名时提示“用户名已存在”的验证功能?

解决Knex操作MySQL注册接口重复用户名导致服务器崩溃的问题

你当前的问题是:MySQL表中username字段已设唯一约束,但注册重复用户名时服务器直接崩溃,无法返回友好的错误提示。原代码里的验证逻辑未生效,核心原因是既没在插入前做前置检查,也没捕获数据库的唯一键冲突异常。

原问题代码

注册接口代码

exports.signup = async (req, res) => {
  const { username, password, name } = req.body;

  // TODO: Validate if username exists
  
  await knex("users").insert({ username, password, name });
  
  const user = await knex("users").where({ username }).first();

  // const users = await knex("users").where({username});
  
  
  // if (users === username) {
  //   res.status(401).json({
  //     error: {
  //       message: "Username already exists"
  //     }
  //   })
  // } else {
    const token = jwt.sign({ username, id: user.id }, secret);
    console.log(token);
    res.json({ ...user, token });
  // }
};

数据库迁移代码

exports.up = function (knex) {
  return knex.schema.createTable("users", (table) => {
    table.increments('id').primary();
    table.string("username").notNullable().unique();
    table.string("password").notNullable();
    table.string("name").notNullable();
  });
};

exports.down = function (knex) {
  return knex.schema.dropTable("users");
};

解决方法

要彻底解决问题,需要做两步:前置查询验证 + 捕获数据库异常,覆盖常规请求和并发请求场景。

修改后的注册接口代码

exports.signup = async (req, res) => {
  const { username, password, name } = req.body;

  try {
    // 前置检查:查询用户名是否已存在
    const existingUser = await knex("users").where({ username }).first();
    if (existingUser) {
      return res.status(409).json({
        error: {
          message: "用户名已存在"
        }
      });
    }

    // 插入新用户
    await knex("users").insert({ username, password, name });
    
    // 获取刚创建的用户信息并生成token
    const user = await knex("users").where({ username }).first();
    const token = jwt.sign({ username, id: user.id }, secret);
    
    res.json({ ...user, token });
  } catch (err) {
    // 捕获MySQL唯一键冲突异常(处理并发场景)
    if (err.code === 'ER_DUP_ENTRY') {
      return res.status(409).json({
        error: {
          message: "用户名已存在"
        }
      });
    }
    // 其他未知错误返回通用提示
    res.status(500).json({
      error: {
        message: "服务器内部错误"
      }
    });
  }
};

关键说明

  • 前置查询:在插入操作前先校验用户名,快速返回错误,避免触发数据库约束。
  • 异常捕获:MySQL触发唯一键约束时会抛出ER_DUP_ENTRY错误,捕获该错误可避免服务器崩溃,同时覆盖并发请求导致的冲突场景。
  • HTTP状态码选用409(冲突)更贴合业务场景,原代码用401(未授权)语义不准确。

内容的提问来源于stack exchange,提问作者Gin Ichimaru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:57:20