Node.js+MySQL登录系统遇405错误及前后端连接故障排查
问题描述
开发个人爱好项目「患者追踪管理系统」的基础登录功能,侧重数据库创建与前端开发,卡在前后端连接环节:管理员登录功能无法正常运行。后端采用Node.js(Express)+MySQL搭建,前端通过fetch发送POST请求时出现405错误,尝试安装CORS拦截扩展后问题仍未解决。以下为完整前后端、数据库代码:
服务器端代码(server.js)
// server.js const express = require('express'); const mysql = require('mysql'); const bodyParser = require('body-parser'); // Add this line to parse incoming request body const app = express(); // Middleware to parse incoming request body as JSON // app.use(bodyParser.json()); // Establish MySQL connection const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'hospital' }); // Connect to MySQL connection.connect((err) => { if (err) { console.error('Error connecting to MySQL: ' + err.stack); return; } console.log('Connected to MySQL as id ' + connection.threadId); }); // Endpoint to handle login app.get('/login', (req, res) => { const { username, password } = req.query; // Query the database to check the credentials connection.query('SELECT * FROM Admin WHERE Username = ? AND Password = ?', [username, password], (error, results, fields) => { if (error) { console.error('Error querying the database:', error); res.status(500).json({ message: 'An error occurred while processing your request.' }); return; } if (results.length > 0) { // Username and password match res.status(200).json({ message: 'Login successful' }); } else { // Username or password is incorrect res.status(401).json({ message: 'Invalid username or password' }); } }); }); const port = process.env.PORT || 5500; app.listen(port, () => { console.log(`Server running on port ${port}`); });
客户端代码(client_admin.js)
// static/scripts/client_admin.js const usernameInput = document.getElementById("username"); const passwordInput = document.getElementById("password"); const showPasswordButton = document.getElementById("showPassword"); const loginButton = document.getElementById("login"); const messageDiv = document.getElementById("message"); showPasswordButton.addEventListener("click", function() { if (passwordInput.type === "password") { passwordInput.type = "text"; showPasswordButton.textContent = "Hide Password"; } else { passwordInput.type = "password"; showPasswordButton.textContent = "Show Password"; } }); loginButton.addEventListener('click', function() { const username = usernameInput.value; const password = passwordInput.value; // Send a POST request to the server with the username and password fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }) .then(response => { if (response.ok) { messageDiv.textContent = "Login successful"; } else { messageDiv.textContent = "Invalid username or password"; } }) .catch(error => { // Handle any network errors console.error('Error:', error); messageDiv.textContent = "An error occurred while processing your request."; }); }); console.log(window.location.port); // Print the port
管理员页面代码(index_admin_login.html)
<!-- static/index_admin_login.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Login</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="background_container"></div> <div class="title_container"> <h1>Patient Tracking and Management System</h1> </div> <div class="login_container"> <a href="index.html" target="_self"> <button>Back to main page</button> </a> <h2>Admin Login Panel</h2> <label for="username">Username:</label> <input name="username" id="username" type="text" style="height: 20px; width: 100px"> <div></div> <label for="password">Password:</label> <input name="password" id="password" type="password" style="height: 20px; width: 100px"> <div></div> <button id="login" type="submit" style="position: sticky">Login</button> <div></div> <button id="showPassword">Show Password</button> <div id="message"></div> </div> <script src="scripts/client_admin.js"></script> <!-- including the client_admin.js file --> </body> </html>
数据库脚本
CREATE DATABASE Hospital; -- QUERIED 1 USE Hospital; CREATE TABLE Patients ( PatientID INT AUTO_INCREMENT PRIMARY KEY, Name VARCHAR(50), Surname VARCHAR(50), DateOfBirth DATE, Gender VARCHAR(10), TelephoneNumber VARCHAR(20), Adress VARCHAR(255), EmailAdress VARCHAR(255), Password VARCHAR(255) ); CREATE TABLE Doctors ( DoctorID INT AUTO_INCREMENT PRIMARY KEY, Name VARCHAR(50), Surname VARCHAR(50), AreaOfExpertise VARCHAR(100), DoctorsHospital VARCHAR(100), EmailAdress VARCHAR(255), Password VARCHAR(255) ); CREATE TABLE Admin ( AdminID INT AUTO_INCREMENT PRIMARY KEY, Username VARCHAR(255), EmailAdress VARCHAR(255), Password VARCHAR(255) ); CREATE TABLE Appointments ( AppointmentID INT AUTO_INCREMENT PRIMARY KEY, PatientID INT, DoctorID INT, AppointmentDate DATE, AppointmentTime TIME, FOREIGN KEY (PatientID) REFERENCES Patients(PatientID), FOREIGN KEY (DoctorID) REFERENCES Doctors(DoctorID) ); CREATE TABLE Reports ( ReportID INT AUTO_INCREMENT PRIMARY KEY, ReportDate DATE, ReportContent TEXT, FileURL VARCHAR(255), FileType VARCHAR(50), PatientID INT, DoctorID INT, AdminID INT, FOREIGN KEY (PatientID) REFERENCES Patients(PatientID), FOREIGN KEY (DoctorID) REFERENCES Doctors(DoctorID), FOREIGN KEY (AdminID) REFERENCES Admin(AdminID) ); -- QUERIED 2 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; -- QUERIED 3 (for enabling the node.js to work with mysql) INSERT INTO Admin (Username, EmailAdress, Password) VALUES ("admin", "admin@gmail.com", "0123"); -- QUERIED 4 SELECT * FROM Patients; SELECT * FROM Doctors; SELECT * FROM Admin;
使用VS Code的Live Server扩展在Firefox中打开页面时,控制台出现405错误,尝试安装CORS拦截扩展后问题仍未解决。
解决方案
1. 修复请求方法不匹配(405错误核心原因)
后端登录接口定义为app.get('/login')(仅接受GET请求),但前端发送的是POST请求,导致405 Method Not Allowed错误。需同步前后端请求方法,并正确解析请求体:
修改server.js关键部分:
const express = require('express'); const mysql = require('mysql'); const bodyParser = require('body-parser'); const cors = require('cors'); const app = express(); // 启用JSON请求体解析 app.use(bodyParser.json()); // 或使用Express内置方法:app.use(express.json()); // 启用CORS解决跨域 app.use(cors()); // 将登录接口改为POST方法 app.post('/login', (req, res) => { // 从请求体获取参数(POST请求参数不在URL查询串中) const { username, password } = req.body; connection.query('SELECT * FROM Admin WHERE Username = ? AND Password = ?', [username, password], (error, results) => { if (error) { console.error('数据库查询错误:', error); return res.status(500).json({ message: '请求处理出错' }); } if (results.length > 0) { res.status(200).json({ message: '登录成功' }); } else { res.status(401).json({ message: '用户名或密码错误' }); } }); }); // 修改后端端口避免与Live Server冲突 const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`Server running on port ${port}`); });
2. 修正前端fetch请求地址
前端fetch的'/login'会指向Live Server的地址,需改为后端的完整URL。假设后端运行在http://localhost:3000,修改client_admin.js中的fetch部分:
fetch('http://localhost:3000/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) })
3. 解决跨域问题
通过Express的cors中间件处理跨域,无需依赖浏览器扩展:
- 安装CORS包:
npm install cors - 在server.js中引入并启用
app.use(cors())(如上代码所示)
4. 额外安全建议
当前数据库中密码以明文存储,存在安全风险,个人项目可使用bcrypt库加密密码:
- 安装bcrypt:
npm install bcrypt - 注册时加密密码,登录时对比哈希值,避免明文传输和存储。
内容的提问来源于stack exchange,提问作者kaanbuu
相关产品推荐
相关产品推荐

