Python 获取错误“;可疑文件操作“;Django版本后,从Django:3.1.8更新Django:3.1.9
在更新到Django:3.1.9后,我发现这个错误,在Django:3.1.8上,它工作正常。 我有一个带有文件字段的文件模型,如下所示:Python 获取错误“;可疑文件操作“;Django版本后,从Django:3.1.8更新Django:3.1.9,python,python-3.x,django,django-models,Python,Python 3.x,Django,Django Models,在更新到Django:3.1.9后,我发现这个错误,在Django:3.1.8上,它工作正常。 我有一个带有文件字段的文件模型,如下所示: class JobFiles(BaseModel): category = models.CharField(max_length=50, choices=FILE_CATEGORY) job_file = models.FileField('JobFile', upload_to=user_directory_path) 我指定了uplo
class JobFiles(BaseModel):
category = models.CharField(max_length=50, choices=FILE_CATEGORY)
job_file = models.FileField('JobFile', upload_to=user_directory_path)
我指定了upload_to选项,以便每个类别的上载方式不同:
def user_directory_path(instance, filename):
import uuid
if not instance.job_file_name:
instance.job_file_name = filename
if instance.category == 'Job Card':
return f'job_card/{uuid.uuid4()}'
if instance.category == 'Photos':
return f'job_card/photos/{uuid.uuid4()}'
if instance.category == 'Other':
return f'job_card/other/{uuid.uuid4()}'
return f'job_card/other/{uuid.uuid4()}'
生成错误的代码(仔细检查文件是否存在,并将其包装在文件对象中):
我得到的错误是:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.9/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/code/job_cards/views.py", line 311, in job_card_maintenance_create
job_files.save()
File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 753, in save
self.save_base(using=using, force_insert=force_insert,
File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 790, in save_base
updated = self._save_table(
File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 895, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 933, in _do_insert
return manager._insert(
File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1254, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1396, in execute_sql
for sql, params in self.as_sql():
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1339, in as_sql
value_rows = [
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1340, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1340, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1291, in pre_save_val
return field.pre_save(obj, add=True)
File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 308, in pre_save
file.save(file.name, file.file, save=False)
File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 87, in save
name = self.field.generate_filename(self.instance, name)
File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 322, in generate_filename
filename = validate_file_name(filename)
File "/usr/local/lib/python3.9/site-packages/django/core/files/utils.py", line 8, in validate_file_name
raise SuspiciousFileOperation("File name '%s' includes path elements" % name)
Exception Type: SuspiciousFileOperation at /job_cards/create/
Exception Value: File name '/tmp/a1134065293b47c1a054c8fc1481ec93.pdf' includes path elements
回溯(最近一次呼叫最后一次):
文件“/usr/local/lib/python3.9/site packages/django/core/handlers/exception.py”,第47行,在内部
响应=获取响应(请求)
文件“/usr/local/lib/python3.9/site packages/django/core/handlers/base.py”,第181行,在get响应中
响应=包装的回调(请求,*回调参数,**回调参数)
文件“/usr/local/lib/python3.9/site packages/django/contrib/auth/decorators.py”,第21行,在包装视图中
返回视图功能(请求,*args,**kwargs)
文件“/code/job\u cards/views.py”,第311行,在job\u card\u maintenance\u create中
作业\u文件。保存()
文件“/usr/local/lib/python3.9/site packages/django/db/models/base.py”,第753行,保存
self.save_base(使用=使用,强制插入=强制插入,
save_base中的文件“/usr/local/lib/python3.9/site packages/django/db/models/base.py”,第790行
更新=自我保存表格(
文件“/usr/local/lib/python3.9/site packages/django/db/models/base.py”,第895行,在保存表中
结果=self.\u do\u insert(cls.\u基本\u管理器,使用,字段,返回\u字段,原始)
文件“/usr/local/lib/python3.9/site packages/django/db/models/base.py”,第933行,插入
退货经理。\u插入(
文件“/usr/local/lib/python3.9/site packages/django/db/models/manager.py”,第85行,在manager\u方法中
返回getattr(self.get_queryset(),name)(*args,**kwargs)
文件“/usr/local/lib/python3.9/site packages/django/db/models/query.py”,第1254行,插入
return query.get\u编译器(using=using).execute\u sql(返回\u字段)
文件“/usr/local/lib/python3.9/site packages/django/db/models/sql/compiler.py”,第1396行,在execute\u sql中
对于sql,self.as_sql()中的参数为:
as_sql中的文件“/usr/local/lib/python3.9/site packages/django/db/models/sql/compiler.py”,第1339行
值_行=[
文件“/usr/local/lib/python3.9/site packages/django/db/models/sql/compiler.py”,第1340行,在
[self.prepare_值(字段,self.pre_保存值(字段,对象))用于字段中的字段]
文件“/usr/local/lib/python3.9/site packages/django/db/models/sql/compiler.py”,第1340行,在
[self.prepare_值(字段,self.pre_保存值(字段,对象))用于字段中的字段]
文件“/usr/local/lib/python3.9/site packages/django/db/models/sql/compiler.py”,第1291行,保存前
返回字段。预保存(obj,add=True)
文件“/usr/local/lib/python3.9/site packages/django/db/models/fields/files.py”,第308行,保存前
file.save(file.name,file.file,save=False)
文件“/usr/local/lib/python3.9/site packages/django/db/models/fields/files.py”,保存中第87行
name=self.field.generate_文件名(self.instance,name)
文件“/usr/local/lib/python3.9/site packages/django/db/models/fields/files.py”,第322行,位于generate_文件名中
filename=验证文件名(filename)
文件“/usr/local/lib/python3.9/site packages/django/core/files/utils.py”,第8行,验证文件名
引发可疑文件操作(“文件名“%s”包括路径元素“%name”)
异常类型:可疑文件操作位于/job\u cards/create/
异常值:文件名“/tmp/a1134065293b47c1a054c8fc1481ec93.pdf”包含路径元素
我的尝试:
降级至3.1.8(工程)
向FileField传递一个字符串可以工作,但是它不会执行upload\u to。
试图将文件保存在“基本”文件夹和“媒体”文件夹中(仍然收到相同的错误)这是由于最近发布的CVE-2021-31542的缓解措施我发现django的新缓解代码与项目自身的文件和图像文件默认行为不一致,即从您提供给构造函数的对象复制准确的文件名 对代码应用这样的更改应该可以修复它,就像它修复了我的代码一样:
doc = '/tmp/mergedfile.pdf'
with open(doc, mode='rb') as f:
- job_files.job_file = File(f)
+ job_files.job_file = File(f, name=os.path.basename(doc))
job_files.save()
编辑:django发行版(5月13日,2.23版,2.2.23版,3.1.11版,3.2.3版)中的错误现已修复。我也遇到过这个问题,但需要能够通过编程指定上载目录。此更改使得在传递文件名时无法将文件放入目录中。不过,仍然可以解决这个新问题通过指定自定义函数进行限制 下面是一个围绕此更改工作的提交示例:
+def get_invoice_dir(instance, filename):
+ return "dpnk-{}/{}".format(instance.campaign.pk, filename)
+
+
@with_author
class Invoice(StaleSyncMixin, AbstractOrder):
"""Faktura"""
@@ -103,14 +107,14 @@ class Invoice(StaleSyncMixin, AbstractOrder):
)
invoice_pdf = models.FileField(
verbose_name=_(u"PDF faktury"),
- upload_to=u"invoices",
+ upload_to=get_invoice_dir,
max_length=512,
blank=True,
null=True,
)
invoice_xml = models.FileField(
verbose_name=_("XML faktury"),
- upload_to="invoices",
+ upload_to=get_invoice_dir,
max_length=512,
blank=True,
null=True,
@@ -340,16 +344,13 @@ def create_and_send_invoice_files(sender, instance, created, **kwargs):
if not instance.invoice_pdf or not instance.invoice_xml:
invoice_data = invoice_gen.generate_invoice(instance)
instance.total_amount = invoice_data.price_tax
- filename = "dpnk-%s/%s" % (
- instance.campaign.pk,
- slugify(
- "invoice_%s_%s_%s_%s"
- % (
- instance.sequence_number,
- instance.company.name[0:40],
- instance.exposure_date.strftime("%Y-%m-%d"),
- uuid.uuid4(),
- ),
+ filename = slugify(
+ "invoice_%s_%s_%s_%s"
+ % (
+ instance.sequence_number,
+ instance.company.name[0:40],
+ instance.exposure_date.strftime("%Y-%m-%d"),
+ uuid.uuid4(),
),
)
- 解决此问题的最佳方法是升级到Django 2.2.23或任何最新版本的Django,因为此回归已经修复:)
感谢您的帮助该漏洞现已在django版本中修复,该版本于今天5月13日发布,版本为2.2.23、3.1.11、3.2.3
+def get_invoice_dir(instance, filename):
+ return "dpnk-{}/{}".format(instance.campaign.pk, filename)
+
+
@with_author
class Invoice(StaleSyncMixin, AbstractOrder):
"""Faktura"""
@@ -103,14 +107,14 @@ class Invoice(StaleSyncMixin, AbstractOrder):
)
invoice_pdf = models.FileField(
verbose_name=_(u"PDF faktury"),
- upload_to=u"invoices",
+ upload_to=get_invoice_dir,
max_length=512,
blank=True,
null=True,
)
invoice_xml = models.FileField(
verbose_name=_("XML faktury"),
- upload_to="invoices",
+ upload_to=get_invoice_dir,
max_length=512,
blank=True,
null=True,
@@ -340,16 +344,13 @@ def create_and_send_invoice_files(sender, instance, created, **kwargs):
if not instance.invoice_pdf or not instance.invoice_xml:
invoice_data = invoice_gen.generate_invoice(instance)
instance.total_amount = invoice_data.price_tax
- filename = "dpnk-%s/%s" % (
- instance.campaign.pk,
- slugify(
- "invoice_%s_%s_%s_%s"
- % (
- instance.sequence_number,
- instance.company.name[0:40],
- instance.exposure_date.strftime("%Y-%m-%d"),
- uuid.uuid4(),
- ),
+ filename = slugify(
+ "invoice_%s_%s_%s_%s"
+ % (
+ instance.sequence_number,
+ instance.company.name[0:40],
+ instance.exposure_date.strftime("%Y-%m-%d"),
+ uuid.uuid4(),
),
)