feat: 多班级版 v2.0 - Go后端重写 + 43轮代码审查

- 后端从 Python FastAPI 重写为 Go Gin(端口 56789)
- 多班级完全隔离
- 超级管理员独立登录
- 课代表作业管理、排行榜分项排行
- 角色加减分上下限可配置
- 家长改密功能(可开关)
- 周度/月度重置功能
- MySQL 5.7 兼容
- 43轮代码审查+全部修复
- Apache 2.0 许可证
This commit is contained in:
2026-06-22 10:06:10 +08:00
parent 4084afc53c
commit d6dec878bd
214 changed files with 12622 additions and 9725 deletions

View File

@@ -1,11 +1,11 @@
<?php
/**
* 班级操行分管理系统 - Session 保存接口
* 多班级版班级管理系统 - Session 保存接口
*
* 开发者: Canglan
* 联系方式: admin@sea-studio.top
* 版权归属: Sea Network Technology Studio
* 许可证: MIT License
* 许可证: Apache License 2.0
*
* 版权所有 © Sea Network Technology Studio
*
@@ -27,7 +27,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
// 只允许 POST 请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
@@ -38,6 +37,34 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
exit();
}
// CSRF 防护:验证 Origin/Referer 头确保同源请求
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$host = $_SERVER['HTTP_HOST'] ?? '';
$serverName = $_SERVER['SERVER_NAME'] ?? '';
if (!empty($origin)) {
$parsedOrigin = parse_url($origin, PHP_URL_HOST);
if ($parsedOrigin !== $host && $parsedOrigin !== $serverName) {
http_response_code(403);
echo json_encode([
'success' => false,
'message' => '跨域请求被拒绝'
]);
exit();
}
} elseif (!empty($referer)) {
$parsedReferer = parse_url($referer, PHP_URL_HOST);
if ($parsedReferer !== $host && $parsedReferer !== $serverName) {
http_response_code(403);
echo json_encode([
'success' => false,
'message' => '跨域请求被拒绝'
]);
exit();
}
}
// 获取原始输入
$input = file_get_contents('php://input');
@@ -82,7 +109,7 @@ if (!empty($missingFields)) {
}
// 验证 user_type 是否合法
$validUserTypes = ['student', 'parent', 'admin'];
$validUserTypes = ['student', 'parent', 'admin', 'super_admin'];
if (!in_array($data['user_type'], $validUserTypes)) {
http_response_code(400);
echo json_encode([
@@ -115,8 +142,8 @@ curl_setopt_array($ch, [
'Authorization: Bearer ' . $token,
'Content-Type: application/json'
],
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 0
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2
]);
$apiResponse = curl_exec($ch);
@@ -153,18 +180,23 @@ if ($tokenUserId === null || intval($tokenUserId) !== intval($data['user_id']))
exit();
}
// 设置 Session 变量
$_SESSION['user_id'] = $data['user_id'];
$_SESSION['user_type'] = $data['user_type'];
$_SESSION['username'] = $data['username'];
$_SESSION['real_name'] = $data['real_name'] ?? '';
$_SESSION['role'] = $data['role'] ?? '';
// 从后端 JWT 解析权威数据(不信任客户端传入的 user_type/role
$tokenData_user = $tokenData['data'];
// 登录成功后重新生成 Session ID防止 Session 固定攻击
session_regenerate_id(true);
$_SESSION['user_id'] = intval($tokenData_user['user_id']);
$_SESSION['user_type'] = $tokenData_user['user_type'];
$_SESSION['username'] = $tokenData_user['username'];
$_SESSION['real_name'] = $tokenData_user['real_name'] ?? '';
$_SESSION['role'] = $tokenData_user['role'] ?? '';
$_SESSION['class_id'] = $tokenData_user['class_id'] ?? null;
$_SESSION['class_name'] = $tokenData_user['class_name'] ?? '';
$_SESSION['login_time'] = time();
$_SESSION['jwt_token'] = $token;
// 如果是学生,额外设置 student_id
if ($data['user_type'] === 'student') {
if (empty($data['student_id'])) {
// 如果是学生,额外设置 student_id仅从 JWT 解析,不信任客户端传入值)
if ($_SESSION['user_type'] === 'student') {
$studentId = $tokenData_user['student_id'] ?? null;
if (empty($studentId)) {
http_response_code(400);
echo json_encode([
'success' => false,
@@ -172,7 +204,7 @@ if ($data['user_type'] === 'student') {
]);
exit();
}
$_SESSION['student_id'] = $data['student_id'];
$_SESSION['student_id'] = $studentId;
}
// 保存 Session