path_utils.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. """
  2. 路径验证工具
  3. """
  4. import re
  5. from fastapi import HTTPException
  6. def validate_path(path: str, allow_root: bool = False) -> str:
  7. """
  8. 验证和清理文件路径,防止路径遍历攻击
  9. Args:
  10. path: 要验证的路径
  11. allow_root: 是否允许根路径 "/"
  12. Returns:
  13. 清理后的路径
  14. Raises:
  15. HTTPException: 如果路径无效
  16. """
  17. if not path:
  18. raise HTTPException(status_code=400, detail="路径不能为空")
  19. # 移除开头的斜杠(MinIO 规范)
  20. if path.startswith('/'):
  21. path = path[1:]
  22. # 检查路径遍历攻击
  23. if '..' in path or path.startswith('/') or '//' in path:
  24. raise HTTPException(status_code=400, detail="无效的路径格式,不允许路径遍历")
  25. # 检查危险字符
  26. dangerous_chars = ['<', '>', '|', '\0', '\r', '\n']
  27. for char in dangerous_chars:
  28. if char in path:
  29. raise HTTPException(status_code=400, detail=f"路径包含非法字符: {char}")
  30. # 检查路径长度
  31. if len(path) > 1024:
  32. raise HTTPException(status_code=400, detail="路径长度超过限制")
  33. return path
  34. def sanitize_filename(filename: str) -> str:
  35. """
  36. 清理文件名,移除危险字符
  37. Args:
  38. filename: 原始文件名
  39. Returns:
  40. 清理后的文件名
  41. """
  42. if not filename:
  43. raise HTTPException(status_code=400, detail="文件名不能为空")
  44. # 移除路径分隔符
  45. filename = filename.replace('/', '').replace('\\', '')
  46. # 移除危险字符
  47. dangerous_chars = ['<', '>', '|', ':', '"', '?', '*', '\0']
  48. for char in dangerous_chars:
  49. filename = filename.replace(char, '_')
  50. # 限制长度
  51. if len(filename) > 255:
  52. name, ext = filename.rsplit('.', 1) if '.' in filename else (filename, '')
  53. filename = name[:250] + ('.' + ext if ext else '')
  54. return filename