""" 路径验证工具 """ import re import os from fastapi import HTTPException def validate_path(path: str, allow_root: bool = False) -> str: """ 验证和清理文件路径,防止路径遍历攻击 Args: path: 要验证的路径 allow_root: 是否允许根路径 "/" Returns: 清理后的路径 Raises: HTTPException: 如果路径无效 """ if not path: raise HTTPException(status_code=400, detail="路径不能为空") # 移除开头的斜杠(MinIO 规范) if path.startswith('/'): path = path[1:] # 检查路径遍历攻击 if '..' in path or path.startswith('/') or '//' in path: raise HTTPException(status_code=400, detail="无效的路径格式,不允许路径遍历") # 检查危险字符 dangerous_chars = ['<', '>', '|', '\0', '\r', '\n'] for char in dangerous_chars: if char in path: raise HTTPException(status_code=400, detail=f"路径包含非法字符: {char}") # 检查路径长度 if len(path) > 1024: raise HTTPException(status_code=400, detail="路径长度超过限制") return path def sanitize_filename(filename: str) -> str: """ 清理文件名,移除危险字符 Args: filename: 原始文件名 Returns: 清理后的文件名 """ if not filename: raise HTTPException(status_code=400, detail="文件名不能为空") filename = os.path.basename(filename) # 移除路径分隔符 filename = filename.replace('/', '').replace('\\', '') # 移除危险字符 dangerous_chars = ['<', '>', '|', ':', '"', '?', '*', '\0'] for char in dangerous_chars: filename = filename.replace(char, '_') # 限制长度 if len(filename) > 255: name, ext = filename.rsplit('.', 1) if '.' in filename else (filename, '') filename = name[:250] + ('.' + ext if ext else '') return filename