v0.1测试

This commit is contained in:
2026-04-07 17:07:13 +08:00
parent 593973f598
commit 6b1b586fe3
80 changed files with 9073 additions and 32 deletions

131
backend/utils/security.py Normal file
View File

@@ -0,0 +1,131 @@
# ===========================================
# 班级操行分管理系统 - 后端服务
#
# 开发者: Canglan
# 联系方式: admin@sea-studio.top
# 版权归属: Sea Network Technology Studio
# 许可证: MIT License
#
# 版权所有 © Sea Network Technology Studio
# ===========================================
import hashlib
import secrets
import re
from config import settings
class SecurityUtils:
"""安全工具类"""
@staticmethod
def sha1_md5_password(password: str) -> str:
"""
双重加密sha1 + md5
流程:原始密码 -> sha1 -> 加盐 -> md5
"""
# 第一层SHA1
sha1_hash = hashlib.sha1(password.encode('utf-8')).hexdigest()
# 加盐
salted = sha1_hash + settings.PASSWORD_SALT
# 第二层MD5
md5_hash = hashlib.md5(salted.encode('utf-8')).hexdigest()
return md5_hash
@staticmethod
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""验证密码"""
return SecurityUtils.sha1_md5_password(plain_password) == hashed_password
@staticmethod
def generate_random_password(length: int = 8) -> str:
"""生成随机密码"""
alphabet = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'
return ''.join(secrets.choice(alphabet) for _ in range(length))
@staticmethod
def validate_password_strength(password: str) -> tuple:
"""
验证密码强度
返回: (是否有效, 错误信息)
"""
if len(password) < 6:
return False, "密码长度至少6位"
if len(password) > 20:
return False, "密码长度不能超过20位"
# 检查是否包含至少一个数字
if not any(c.isdigit() for c in password):
return False, "密码必须包含至少一个数字"
# 检查是否包含至少一个字母
if not any(c.isalpha() for c in password):
return False, "密码必须包含至少一个字母"
return True, ""
@staticmethod
def sanitize_string(value: str, max_length: int = 255) -> str:
"""
清理字符串输入
- 去除首尾空格
- 限制长度
- 转义特殊字符
"""
if not value:
return ""
# 去除首尾空格
value = value.strip()
# 限制长度
if len(value) > max_length:
value = value[:max_length]
# 转义HTML特殊字符防止XSS
html_chars = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'/': '&#x2F;'
}
for char, escape in html_chars.items():
value = value.replace(char, escape)
return value
@staticmethod
def validate_student_no(student_no: str) -> bool:
"""验证学号格式(数字+字母长度4-20"""
if not student_no:
return False
if len(student_no) < 4 or len(student_no) > 20:
return False
# 字母数字组合
return student_no.isalnum()
@staticmethod
def validate_phone(phone: str) -> bool:
"""验证手机号格式(中国手机号)"""
if not phone:
return False
pattern = r'^1[3-9]\d{9}$'
return bool(re.match(pattern, phone))
@staticmethod
def validate_points_change(points: int, max_abs: int = 100) -> tuple:
"""
验证分值变动
返回: (是否有效, 错误信息)
"""
if points == 0:
return False, "分值不能为0"
if abs(points) > max_abs:
return f"单次分值变动不能超过{max_abs}"
return True, ""
# 单例导出
security = SecurityUtils()