From 4972d1e3be72776100f08e82287121071f79caff Mon Sep 17 00:00:00 2001 From: canglan Date: Thu, 16 Apr 2026 14:20:49 +0800 Subject: [PATCH] =?UTF-8?q?v0.8.8=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/utils/security.py | 17 +++++++++++------ frontend/admin/conduct.php | 20 +++++++++++++++++--- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/backend/utils/security.py b/backend/utils/security.py index 4638cc6..edba94b 100644 --- a/backend/utils/security.py +++ b/backend/utils/security.py @@ -47,6 +47,7 @@ class SecurityUtils: def validate_password_strength(password: str) -> tuple: """ 验证密码强度 + 要求:大小写字母、数字、特殊符号 至少包含其中3种 返回: (是否有效, 错误信息) """ if len(password) < 6: @@ -54,13 +55,17 @@ class SecurityUtils: if len(password) > 20: return False, "密码长度不能超过20位" - # 检查是否包含至少一个数字 - if not any(c.isdigit() for c in password): - return False, "密码必须包含至少一个数字" + # 检查四种字符类型 + has_upper = any(c.isupper() for c in password) # 大写字母 + has_lower = any(c.islower() for c in password) # 小写字母 + has_digit = any(c.isdigit() for c in password) # 数字 + has_special = any(not c.isalnum() for c in password) # 特殊符号 - # 检查是否包含至少一个字母 - if not any(c.isalpha() for c in password): - return False, "密码必须包含至少一个字母" + # 统计满足的字符类型数量 + char_types = sum([has_upper, has_lower, has_digit, has_special]) + + if char_types < 3: + return False, "密码必须包含大写字母、小写字母、数字、特殊符号中的至少3种" return True, "" diff --git a/frontend/admin/conduct.php b/frontend/admin/conduct.php index ae62e45..1e23e20 100644 --- a/frontend/admin/conduct.php +++ b/frontend/admin/conduct.php @@ -144,16 +144,30 @@ async function exportMoralityRecords() { student_no: student.student_no, name: student.name, total_points: student.total_points || 0, - positive_history: positiveRecords.join(','), - negative_history: negativeRecords.join(',') + positive_history: positiveRecords.join('; '), + negative_history: negativeRecords.join('; ') }); } + // CSV字段转义函数 + function escapeCsvField(field) { + if (field === null || field === undefined) return ''; + // 移除换行符和回车符 + let str = String(field).replace(/[\r\n]+/g, ' '); + // 转义双引号 + str = str.replace(/"/g, '""'); + // 如果包含逗号、分号、双引号或空格,用双引号包裹 + if (/[\,\;\"\s]/.test(str)) { + str = '"' + str + '"'; + } + return str; + } + // 构建CSV内容 let csv = '\uFEFF'; // BOM for UTF-8 csv += '学号,姓名,分数,加分历史,减分记录\n'; studentRecords.forEach(s => { - csv += `${s.student_no},${s.name},${s.total_points},"${(s.positive_history || '').replace(/"/g, '""')}","${(s.negative_history || '').replace(/"/g, '""')}"\n`; + csv += `${escapeCsvField(s.student_no)},${escapeCsvField(s.name)},${escapeCsvField(s.total_points)},${escapeCsvField(s.positive_history)},${escapeCsvField(s.negative_history)}\n`; }); // 下载文件