nodebookls/security.py
2025-10-29 13:56:24 +08:00

112 lines
3.1 KiB
Python

import os
import hashlib
import re
from typing import Tuple
from exceptions import SecurityError
class SecurityManager:
"""安全管理器"""
def __init__(self):
self.allowed_extensions = {'.txt'}
self.max_file_size = 10 * 1024 * 1024 # 10MB
self.suspicious_patterns = [
r'<script[^>]*>.*?</script>', # JavaScript代码
r'javascript:', # JavaScript协议
r'on\w+\s*=', # 事件处理器
r'<iframe[^>]*>', # iframe标签
r'<object[^>]*>', # object标签
r'<embed[^>]*>', # embed标签
]
def validate_file(self, file_path: str) -> Tuple[bool, str]:
"""
验证文件安全性
Args:
file_path: 文件路径
Returns:
(is_valid, error_message)
"""
try:
# 检查文件是否存在
if not os.path.exists(file_path):
return False, "文件不存在"
# 检查文件大小
file_size = os.path.getsize(file_path)
if file_size > self.max_file_size:
return False, f"文件大小超过限制 ({self.max_file_size} bytes)"
# 检查文件扩展名
_, ext = os.path.splitext(file_path)
if ext.lower() not in self.allowed_extensions:
return False, f"不支持的文件类型: {ext}"
return True, ""
except Exception as e:
return False, f"文件验证失败: {str(e)}"
def sanitize_text(self, text: str) -> str:
"""
清理文本中的潜在危险内容
Args:
text: 输入文本
Returns:
清理后的文本
"""
# 移除潜在的恶意代码
for pattern in self.suspicious_patterns:
text = re.sub(pattern, '', text, flags=re.IGNORECASE | re.DOTALL)
# 移除HTML标签
text = re.sub(r'<[^>]*>', '', text)
# 限制文本长度
max_length = 100000 # 100KB
if len(text) > max_length:
text = text[:max_length]
return text
def hash_password(self, password: str) -> str:
"""
哈希密码
Args:
password: 明文密码
Returns:
哈希后的密码
"""
# 使用SHA-256哈希
return hashlib.sha256(password.encode('utf-8')).hexdigest()
def verify_password(self, password: str, hashed: str) -> bool:
"""
验证密码
Args:
password: 明文密码
hashed: 哈希后的密码
Returns:
是否匹配
"""
return self.hash_password(password) == hashed
def generate_secure_token(self) -> str:
"""
生成安全令牌
Returns:
安全令牌
"""
# 使用系统随机数生成器
return hashlib.sha256(os.urandom(32)).hexdigest()
# 创建全局安全管理器实例
security_manager = SecurityManager()