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

Express NodeJS:POST请求后如何向HTML页面追加<p>元素?

问题描述

我正在用Express搭建基础登录系统,需要通过MySQL数据库验证用户名和密码是否正确。收到POST请求后,想在原登录页面底部追加“Success!”或“Failure”提示文本,但用res.write("<p>Success!</p>")和res.send("<p>Success!</p>")都只生成了只有提示的新页面,没法追加到原页面。相关代码如下,请问怎么实现向HTML页面底部追加<p>元素/文本?

原HTML代码

<html>
    <head>
        <meta charset="utf-8">
        <title>Login</title>
    </head>
    <body>
        <h1>Login</h1>
        <form id="contact-form" method="POST" action="/login">
            <label for="Username">Username: </label>
            <input name="Username" maxlength="45"><br><br>

            <label for="Password">Password: </label>
            <input name="Password" type="password" maxlength="45"><br><br>

            <input type="submit" value="Submit">
        </form>
    </body>
</html>

原Express代码

const port = 3000;

const express = require("express");
const mysql = require("mysql2");
const app = express();
const bodyParser = require("body-parser");

var conn = mysql.createConnection({
    host: "localhost",
    database: "database",
    user: "<Username>",
    password: "<Password>"
});

conn.connect((err) => {
    if(err) throw err;
    console.log("Connected to database.");
})


app.use(express.static(__dirname + "/public"));

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

app.get("/login", (req, res) => {
    res.sendFile(__dirname + "/Login.html");
});

app.post("/login", (req,res) => {
    let form = req.body;
    let sqlQuery = "SELECT * FROM logins WHERE Username = '" + form.Username + "' AND Password = '" + form.Password + "';";
    conn.query(sqlQuery, (err, result, fields) => {
        if(err) throw err;
        if(result.length == 1) {
            res.write("<p>Success!</p>")
        } else {
            res.write("<p>Failure.</p>")
        }
    })
});

app.listen(port);

解决方案

直接用res.sendFile或res.write无法修改已存在的页面内容,有两种常用实现方式:

方法一:使用模板引擎(服务器端渲染)

通过模板引擎动态渲染带提示信息的页面,推荐用EJS(上手简单):

  1. 安装EJS
npm install ejs
  1. 配置Express使用EJS
    在你的JS代码中添加:
app.set('view engine', 'ejs');
app.set('views', __dirname); // 指定模板文件所在目录,这里和原HTML同目录
  1. 修改原HTML为EJS模板(重命名为Login.ejs),预留提示位置
<html>
    <head>
        <meta charset="utf-8">
        <title>Login</title>
    </head>
    <body>
        <h1>Login</h1>
        <form id="contact-form" method="POST" action="/login">
            <label for="Username">Username: </label>
            <input name="Username" maxlength="45" value="<%= username || '' %>"><br><br>

            <label for="Password">Password: </label>
            <input name="Password" type="password" maxlength="45"><br><br>

            <input type="submit" value="Submit">
        </form>
        <!-- 动态渲染提示文本 -->
        <% if (message) { %>
            <p><%= message %></p>
        <% } %>
    </body>
</html>
  1. 修改Express路由逻辑
// GET路由改为渲染模板
app.get("/login", (req, res) => {
    res.render('Login', { message: null, username: null });
});

// POST路由验证后传递提示信息
app.post("/login", (req,res) => {
    let { Username, Password } = req.body;
    // 修复SQL注入风险:用参数化查询
    let sqlQuery = "SELECT * FROM logins WHERE Username = ? AND Password = ?;";
    conn.query(sqlQuery, [Username, Password], (err, result) => {
        if(err) throw err;
        let message = result.length === 1 ? "Success!" : "Failure.";
        // 渲染页面并传递提示信息和用户输入的用户名
        res.render('Login', { message, username: Username });
    })
});

方法二:前端AJAX提交(无刷新页面)

通过前端JS异步提交表单,动态在页面添加提示,无需刷新页面:

  1. 修改原HTML,添加提示容器和JS逻辑
<html>
    <head>
        <meta charset="utf-8">
        <title>Login</title>
    </head>
    <body>
        <h1>Login</h1>
        <form id="contact-form">
            <label for="Username">Username: </label>
            <input name="Username" maxlength="45"><br><br>

            <label for="Password">Password: </label>
            <input name="Password" type="password" maxlength="45"><br><br>

            <input type="submit" value="Submit">
        </form>
        <!-- 提示文本容器 -->
        <div id="message-container"></div>

        <script>
            const form = document.getElementById('contact-form');
            const messageContainer = document.getElementById('message-container');

            form.addEventListener('submit', async (e) => {
                e.preventDefault(); // 阻止表单默认刷新提交
                const formData = new FormData(form);
                
                try {
                    const response = await fetch('/login', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded',
                        },
                        body: new URLSearchParams(formData),
                    });
                    const result = await response.json();
                    // 清空旧提示,添加新提示
                    messageContainer.innerHTML = `<p>${result.message}</p>`;
                } catch (err) {
                    messageContainer.innerHTML = `<p>请求出错</p>`;
                }
            });
        </script>
    </body>
</html>
  1. 修改Express POST路由,返回JSON数据
app.post("/login", (req,res) => {
    let { Username, Password } = req.body;
    // 参数化查询避免SQL注入
    let sqlQuery = "SELECT * FROM logins WHERE Username = ? AND Password = ?;";
    conn.query(sqlQuery, [Username, Password], (err, result) => {
        if(err) {
            console.error(err);
            return res.json({ message: "请求出错" });
        }
        let message = result.length === 1 ? "Success!" : "Failure.";
        res.json({ message });
    })
});

重要提醒

你原代码中的SQL查询直接拼接用户输入,存在严重的SQL注入风险,必须用参数化查询(即代码中用?占位符,参数放在数组中传递),否则攻击者可以通过构造特殊输入篡改数据库或窃取数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:40:28