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

使用Joi做用户校验时触发Cannot read property 'string' of undefined错误如何解决

问题修复方案

1 错误原因梳理

  • 初始TypeError: Cannot read property 'string' of undefined报错:你安装的@hapo/joi为非官方兼容包,导出规则与官方Joi不一致,导致引入的joi变量为undefined,调用joi.string触发属性读取报错。
  • 改后password: Path password is required报错:存在三处核心错误:
    • Joi校验方法使用错误:官方Joi v16+版本使用schema.validate(data)的方式调用校验,而非joi.valid(data, schema),valid是枚举值校验的内置方法,不用于全局schema校验
    • 校验方法引入错误:校验文件导出的是包含userValidation属性的对象,你直接将整个导出对象赋值给userValidation变量,调用时没有取到实际的校验方法,导致输入校验失效
    • 新用户实例赋值错误:加密后的密码存储在局部变量hashedPassword中,你错误从req.body.hashedPassword取值,导致存入数据库的password字段为undefined,触发mongoose的必填校验

2 修正代码

2.1 修正校验文件(validation.js)

//validation
const joi = require('joi');
// 用户创建校验规则
const userValidation = (data) => {
    const schema = joi.object({
        username: joi.string().min(6).required(),
        password: joi.string().min(6).required(),
        // 新增二次密码校验逻辑,适配前端表单的password2字段
        password2: joi.string().valid(joi.ref('password')).required().messages({'any.only': '两次输入密码不一致'})
    });
    return schema.validate(data);
};
// 登录校验规则
const loginValidation = (data) => {
    const schema = joi.object({
        username: joi.string().min(6).required(),
        password: joi.string().min(6).required()
    });
    return schema.validate(data);
};
// 导出校验方法
module.exports.userValidation = userValidation;
module.exports.loginValidation = loginValidation;

2.2 修正createUser回调的引入和赋值逻辑

const expressValidator = require('express-validator');
// 修正拼写错误:原bycrypt为笔误,正确包名为bcrypt
const bcrypt = require('bcryptjs');
const bodyparser = require("body-parser");     
const passport = require('passport');
const flash = require('express-session');
// 修正引入:解构取出导出对象里的userValidation方法
const { userValidation } = require('./validation');
// 若之前未引入userSchema请补充:const userSchema = require('../models/你的user模型文件路径');

exports.createUser = async(req, res, next) => {
console.log('Post CREATE User /create-user');
// 校验用户输入
const { error } = userValidation(req.body);
// 校验不通过时返回错误
if (error) {
    return res.status(400).send(error.details[0].message);
}
try {
    // 检查用户是否已存在
    const userExist = await userSchema.findOne({ username: req.body.username });
    if (userExist) return res.status(400).send('UserName Already Exist');
    // 密码哈希处理
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(req.body.password, salt);
    // 修正赋值:直接使用局部变量hashedPassword,不需要从req.body取值
    const user = new userSchema({
        username: req.body.username,
        password: hashedPassword
    })
    // 将用户数据存入数据库
    await user.save();
    res.redirect('/halalMunchies/all-employees');
} catch (error) {
    console.log(error);
    res.status(500).send({
        message: error.message || "Some error occured while creating user"
    });
}
};

3 额外配置确认

请确认express入口文件已经配置了body-parser的表单解析中间件,否则req.body无法读取到表单提交的内容:

app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());

内容的提问来源于stack exchange,提问作者Hesham Eldawy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:36:04