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

使用express.urlencoded后req.body仍为undefined的问题排查

Express项目中req.body始终为undefined的排查与解决

问题背景

已在Express项目中配置app.use(express.urlencoded({ extended: false}))处理表单数据,且HTML表单所有input元素的name属性与代码匹配,但req.body始终返回undefined。相关代码如下:

原JavaScript代码

//Constantes
const express = require('express');
const port = process.env.PORT || 3000;
const exphbs = require("express-handlebars");
const passport = require("passport");               
const session = require("express-session"); 

//---------------
const bcrypt = require("bcrypt");   
const passport_local = require("passport-local");
const LocalStrategy = passport_local.Strategy;
const connection = require("./database");  
//-----------------


//Config
const app = express();
app.use(express.urlencoded({ extended: false}));
app.engine(".hbs", exphbs.engine());
app.set('view engine', ".hbs");

//--------------------

passport.use("local.signup", new LocalStrategy({
    usernameField: "email",
    passwordField: "password",
    passReqToCallback: true
}, async (username, password, req, done) => {
    console.log(req.body);
    const salt = await bcrypt.genSalt(10);
    const hash = await bcrypt.hash(password, salt);
    const user = { email: username, password: hash, nombre: req.body.nombre, apellido: req.body.apellido};
    const result = await connection.query("INSERT INTO usuarios SET ?", user);

    user.id = result.insertId;
    return done(null, user.id);
}));

passport.serializeUser((user, done) => {  
    return done(null, user.id);
 });
 passport.deserializeUser( async (id, done) => {    
     const rows = await connection.query(`SELECT id, email FROM usuarios WHERE id = ${id}`)
     return done(null, rows[0]);
 });

//-----------------------------------
app.use(passport.initialize());
app.use(session({
    secret: "secreto",  
    resave: false,
    saveUninitialized: true,
}));
app.use(passport.session());
app.listen(port, () => {
    console.log("listening on port " + port);
});

app.use(require("./routes/index.js"));
app.use(require("./routes/register.js"));

原HTML表单代码

<!-- Formulario de registro -->
<section class="container-fluid">
    <div class="row justify-content-center align-content-center m-5">
        <h1 class="text-center mt-5">Registro Administrador</h1>
        <div class="col-xl-4 col-lg-8 col-md-8 col-xs-12">
            <form action="/register" method="post" class=" border border-2 border-dark p-4 rounded">
                <div class="form-group p-2">
                    <label for="email">E-Mail <span class="text-danger">*</span></label>
                     <input id="email" class="form-control" type="email" placeholder="marcos@example.com" required name="email"  value="{{ email }}">
                </div>
                <div class="form-group p-2">
                    <label for="password">Contraseña <span class="text-danger">*</span></label>
                     <input id="password" class="form-control" type="password" placeholder="*********" required name="password">
                </div>
                <div class="form-group p-2">
                    <label for="nombre">nombre <span class="text-danger">*</span></label>
                     <input id="nombre" class="form-control" type="text" placeholder="nombre" required name="nombre">
                </div>
                <div class="form-group p-2">
                    <label for="apellido">apellido <span class="text-danger">*</span></label>
                     <input id="apellido" class="form-control" type="text" placeholder="apellido" required name="apellido">
                </div>
                <div class="d-grid p-2">
                    <button type="submit" class="btn btn-light btn-outline-dark outline">Registrarse</button>
                </div>
                <div class="d-grid p-2 ">
                    <a href="/login" class="btn btn-light btn-outline-dark outline">Ya tenes cuenta? Logeate!</a>
                </div>
            </form>
        </div>
    </div>
</section>

排查出的问题点

  1. Passport LocalStrategy回调参数顺序错误
    当设置passReqToCallback: true时,回调函数的第一个参数必须是req(请求对象),原代码中将username放在首位,导致req参数被错误赋值为done函数,无法获取表单数据。

  2. Session与Passport中间件顺序颠倒
    express-session中间件必须在passport.initialize()和passport.session()之前注册,否则Passport无法正确利用session管理认证状态,可能导致请求处理异常。

  3. app.listen()位置不当
    app.listen()应放在所有中间件、路由注册完成之后,确保所有配置生效。原代码中app.listen()提前执行,虽不影响语法,但不符合Express最佳实践,可能引发潜在加载问题。

修复后的代码

调整Passport策略回调参数顺序

passport.use("local.signup", new LocalStrategy({
    usernameField: "email",
    passwordField: "password",
    passReqToCallback: true
}, async (req, username, password, done) => { // 将req调整为第一个参数
    console.log(req.body); // 现在可正常获取表单数据
    const salt = await bcrypt.genSalt(10);
    const hash = await bcrypt.hash(password, salt);
    const user = { email: username, password: hash, nombre: req.body.nombre, apellido: req.body.apellido};
    const result = await connection.query("INSERT INTO usuarios SET ?", user);

    user.id = result.insertId;
    return done(null, user.id);
}));

调整中间件与服务器启动顺序

// 先注册session中间件
app.use(session({
    secret: "secreto",  
    resave: false,
    saveUninitialized: true,
}));
// 再初始化Passport
app.use(passport.initialize());
app.use(passport.session());

// 注册路由
app.use(require("./routes/index.js"));
app.use(require("./routes/register.js"));

// 最后启动服务器
app.listen(port, () => {
    console.log("listening on port " + port);
});

验证方法

  • 重启Express服务器,提交注册表单,查看控制台输出的req.body,应能显示完整的表单字段数据。
  • 检查数据库,确认用户信息被正确插入,说明req.body.nombre、req.body.apellido等字段已正常读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:21:25