Django 3.2.8部署环境(debug=false)触发SuspiciousFileOperation路径遍历异常
问题根因
- Django
FileField的upload_to回调要求返回相对storage根目录的路径,你当前的get_folder方法返回的是从settings.TEMPLATES_FOLDER开头的绝对路径,生产模式下(debug=False)Django会开启严格的路径安全校验,判定该路径存在遍历风险。 - Django 3.2.8版本对
Path类型的返回值存在校验逻辑缺陷,拼接后的绝对路径无法正确通过根目录归属校验,debug模式下该校验不会触发,因此开发环境运行正常。 post_save信号未触发是因为路径校验异常抛出在模型写入数据库之前。
解决方案
方案1:修改upload_to返回相对路径(最简便)
直接修改get_folder方法,返回相对于MEDIA_ROOT的相对路径即可:
def get_folder(self, filename): filename_PATH = Path(filename) template_dir = filename_PATH.stem # 返回相对路径:TEMPLATES/文件名前缀/原文件名 return str(Path("TEMPLATES") / template_dir / filename)
方案2:自定义存储指定根目录
如果你需要保留存储类的独立性,可直接给OverwriteStorage指定根目录为TEMPLATES_FOLDER,此时upload_to只需要返回两级相对路径即可:
# models.py class OverwriteStorage(FileSystemStorage): def __init__(self, *args, **kwargs): kwargs["location"] = settings.TEMPLATES_FOLDER super().__init__(*args, **kwargs) def get_available_name(self, name, max_length=None): self.delete(name) return name class Template(models.Model): def get_folder(self, filename): filename_PATH = Path(filename) template_dir = filename_PATH.stem return str(Path(template_dir) / filename) # 其他字段保持不变 name = models.CharField("template", max_length=32, unique=True) file = models.FileField("templatefile", upload_to=get_folder, null=True, max_length=260, storage=OverwriteStorage())
两种方案任选其一即可解决生产环境的路径校验异常问题。
内容的提问来源于stack exchange,提问作者xtlc
相关产品推荐
相关产品推荐

