主要用于流程学习和kali测试,只用了一台服务器ip为192.168.200.102,采用前后端分离方式,中间件为nginx,waitress-serve,mysql5.7,由于操作系统使用的是之前部署的stream9,而mysql是之前centos7的版本有点兼容性问题,这里不细说了,用其他版本就好。
一、统一文件结构
python_project # Windows本机新建的总文件夹
├── front_end # 前端纯静态文件(3个独立文件,彻底分离)
│ ├── index.html
│ ├── css
│ │ └── style.css
│ └── js
│ └── main.js
│
└── back_end # 后端Python文件(仅1个文件)
└── app.py
二、完整代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>用户信息管理系统</title>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container">
<h1>用户信息管理系统</h1>
<div class="add-form">
<input type="text" id="userName" placeholder="请输入姓名">
<input type="number" id="userAge" placeholder="请输入年龄" min="0" max="150">
<button onclick=addUser()">新增用户</button>
</div>
<table class="user-table">
<thead>
<tr>
<th>用户ID</th>
<th>姓名</th>
<th>年龄</th>
<th>创建时间</th>
</tr>
</thead>
<tbody id="userList">
<tr><td colspan="4" style="color: #999;">加载中...</td></tr>
</tbody>
</table>
</div>
<script src="./js/main.js"></script>
</body>
</html>
*****************************************************************************************************
css
* {margin: 0; padding: 0; box-sizing: border-box; font-family: "微软雅黑";}
.container {width: 800px; margin: 50px auto;}
h1 {text-align: center; color: #333; margin-bottom: 30px;}
.add-form {border: 1px solid #eee; padding: 20px; border-radius: 8px; margin-bottom: 30px;}
.add-form input {padding: 8px 12px; width: 200px; margin-right: 10px; border: 1px solid #ccc; border-radius: 4px; outline: none;}
.add-form input:focus {border-color: #4285F4;}
.add-form button {padding: 8px 20px; background: #4285F4; color: white; border: none; border-radius: 4px; cursor: pointer;}
.add-form button:hover {background: #3367D6;}
.user-table {width: 100%; border-collapse: collapse; text-align: center;}
.user-table th, .user-table td {border: 1px solid #eee; padding: 12px;}
.user-table th {background: #f5f5f5; color: #333;}
.user-table tr:hover {background: #f9f9f9;}
*****************************************************************************************************
js
// 页面加载完成自动查询用户列表
_window.onload = function() {
getUserList();
};
// 查询所有用户
function getUserList() {
fetch('http://192.168.200.102:5000/api/get_users')
.then(res => res.json())
.then(data => {
const userList = document.getElementById('userList');
if (data.code === 200 && data.data.length > 0) {
let html = '';
data.data.forEach(user => {
html += `<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.age || '未填写'}</td>
<td>${user.create_time}</td>
</tr>`;
});
userList[xss_clean] = html;
} else {
userList[xss_clean] = '<tr><td colspan="4" style="color: #999;">暂无用户数据</td></tr>';
}
})
.catch(err => {
alert('查询失败!请检查后端服务是否启动');
});
}
// 新增用户
function addUser() {
const name = document.getElementById('userName').value.trim();
const age = document.getElementById('userAge').value.trim();
if (!name) {
alert('姓名不能为空!');
return;
}
fetch('http://192.168.200.102:5000/api/add_user', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: name, age: age})
})
.then(res => res.json())
.then(data => {
alert(data.msg);
if (data.code === 200) {
document.getElementById('userName').value = '';
document.getElementById('userAge').value = '';
getUserList();
}
})
.catch(err => {
alert('新增失败!请检查后端服务是否启动');
});
}
*****************************************************************************************************
app.py
# 导入所有依赖库
from flask import Flask, request, jsonify
from flask_cors import CORS
import pymysql
# 初始化Flask应用
app = Flask(__name__)
# 解决跨域问题,前端可正常请求后端接口
CORS(app, resources=r'/*', supports_credentials=True)
# ========== 数据库连接配置【Windows调试改IP,服务器运行改localhost】 ==========
def get_db_connection():
conn = pymysql.connect(
host='localhost', # ✅ 服务器运行:写localhost(MySQL在CentOS本机)
# host='192.168.200.102', # ✅ Windows本地调试:写服务器IP
user='root',
password='qwer1234',
database='test_db',
port=3306,
charset='utf8mb4'
)
return conn
# 接口1:查询所有用户 GET请求
@app.route('/api/get_users', methods=['GET'])
def get_users():
conn = get_db_connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('SELECT * FROM user_info ORDER BY id DESC')
users = cursor.fetchall()
cursor.close()
conn.close()
return jsonify({"code": 200, "msg": "查询成功", "data": users})
# 接口2:新增用户 POST请求
@app.route('/api/add_user', methods=['POST'])
def add_user():
name = request.json.get('name')
age = request.json.get('age')
if not name:
return jsonify({"code": 400, "msg": "姓名不能为空!"})
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute('INSERT INTO user_info (name, age) VALUES (%s, %s)', (name, age))
conn.commit()
return jsonify({"code": 200, "msg": "新增用户成功!"})
except Exception as e:
conn.rollback()
return jsonify({"code": 500, "msg": f"新增失败:{str(e)}"})
finally:
cursor.close()
conn.close()
# Windows本地调试启动(服务器部署时不用这个,用waitress启动,这里保留不影响)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
*****************************************************************************************************
三、CentOS Stream9
# 安装Python3和pip3
yum install -y python3 python3-pip -y
# 验证安装成功
python3 -V
pip3 -V
pip3 install flask pymysql flask-cors waitress
# 安装Nginx
yum install -y nginx
# 启动Nginx并设置开机自启
systemctl start nginx
systemctl enable nginx
防火墙
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=5000/tcp --permanent
firewall-cmd --add-port=3306/tcp --permanent
# 重载防火墙规则生效
firewall-cmd --reload
四、上传项目文件到 CentOS 服务器
/usr/share/nginx/front_end
/root/back_end
五、CentOS 服务器
5.1 确认 MySQL 初始化完成
mysql -uroot -pqwer1234
CREATE DATABASE IF NOT EXISTS test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE test_db;
CREATE TABLE IF NOT EXISTS user_info (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
INSERT INTO user_info (name, age) VALUES ('张三',22),('李四',25);
exit;
5.2 配置 Nginx
# 备份原配置文件/usr/share/nginx/
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
# 编辑配置文件
vim /etc/nginx/nginx.conf
server {
listen 80;
server_name localhost;

# 核心:指向服务器上的前端文件夹路径
root /usr/share/nginx/front_end;
index index.html index.htm;
# 解决前端页面刷新404问题
location / {
try_files $uri $uri/ /index.html;
}
}
systemctl restart nginx
5.3 启动 Python 后端服务
# 进入后端代码目录
cd /root/back_end
# 后台启动命令(复制整条执行,无任何修改)
nohup waitress-serve --host=0.0.0.0 --port=5000 app:app > /dev/null 2>&1 &
停止命令
pkill -f waitress-serve
六、最终访问
http://192.168.200.102