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(上手简单):
- 安装EJS
npm install ejs
- 配置Express使用EJS
在你的JS代码中添加:
app.set('view engine', 'ejs'); app.set('views', __dirname); // 指定模板文件所在目录,这里和原HTML同目录
- 修改原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>
- 修改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异步提交表单,动态在页面添加提示,无需刷新页面:
- 修改原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>
- 修改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
相关产品推荐
相关产品推荐

