4

可能重复:
Django(音频)文件验证

我正在构建一个网络应用程序,用户可以在其中上传媒体内容,包括音频文件。

我的AudioFileUploadForm中有一个干净的方法可以验证以下内容:

  • 音频文件不是太大。
  • 音频文件具有有效的 content_type(MIME 类型)。
  • 音频文件具有有效的扩展名。

但是,我担心安全性。用户可以上传带有恶意代码的文件,并轻松通过上述验证。我接下来要做的是验证音频文件确实是一个音频文件(在它写入磁盘之前)。

我该怎么做?

class UploadAudioForm(forms.ModelForm):
    audio_file = forms.FileField()

    def clean_audio_file(self):
        file = self.cleaned_data.get('audio_file',False):
            if file:
                if file._size > 12*1024*1024:
                    raise ValidationError("Audio file too large ( > 12mb )")
                if not file.content_type in ['audio/mpeg','audio/mp4', 'audio/basic', 'audio/x-midi', 'audio/vorbis', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/wav', 'audio/x-wav']:
                    raise ValidationError("Sorry, we do not support that audio MIME type. Please try uploading an mp3 file, or other common audio type.")
                if not os.path.splitext(file.name)[1] in ['.mp3', '.au', '.midi', '.ogg', '.ra', '.ram', '.wav']:
                    raise ValidationError("Sorry, your audio file doesn't have a proper extension.")
                # Next, I want to read the file and make sure it is 
                # a valid audio file. How should I do this? Use a library?
                # Read a portion of the file? ...?
                if not ???.is_audio(file.content):
                    raise ValidationError("Not a valid audio file.")
                return file
            else:
                raise ValidationError("Couldn't read uploaded file")

编辑:通过“验证音频文件确实是音频文件”,我的意思是:

包含音频文件典型数据的文件。我担心用户可能会上传带有适当标题的文件和恶意脚本来代替音频数据。例如... mp3 文件是 mp3 文件吗?或者它是否包含一些不属于 mp3 文件的内容?

4

2 回答 2

5

另一个已发布的header解析答案的替代方案。这意味着有人仍然可以在有效标头后面包含其他数据。

是验证整个文件,这会花费更多的 CPU,但也有更严格的策略。可以做到这一点的库是python audiotools,相关的 API 方法是AudioFile.verify

像这样使用:

import audiotools

f = audiotools.open(filename)
try:
    result = f.verify()
except audiotools.InvalidFile:
    # Invalid file.
    print("Invalid File")
else:
    # Valid file.
    print("Valid File")

警告是这种方法verify非常严格,实际上可以将编码错误的文件标记为无效。您必须自己决定这是否适合您的用例。

于 2013-01-10T18:54:15.777 回答
1

这个想法是使用诸如sndhdr之类的实用程序来尝试读取文件的标题。

from sndhdr import what
import os
from settings import MEDIA_ROOT
...
if what( os.path.join( MEDIA_ROOT, file.name ) ) == None:
# header parse failed, so, it could be a non-audio file.

在这种情况下,您必须确保该实用程序无法将非音频文件识别为音频文件。

我从不使用 sndhdr 实用程序,因此,使用另一个可能会更好。例如还有诱变剂项目。

更新

更专业的方法。

  1. 让用户在没有此类验证的情况下上传他的文件。
  2. 创建与一个文件关联的特殊模型字段:is_checked。默认情况下将字段设置为 False。
  3. 不要让其他用户下载具有 is_checked == False 的文件
  4. 组织一个异步任务,该任务运行一个检查未检查文件的反恶意软件。该软件必须作为 Pythonic 任务中的函数调用。该函数必须回答以下问题:特定文件是否包含恶意软件部分。
  5. 如果当前文件有恶意软件部分,请删除它并删除有关该文件的记录。否则从您的任务中设置 is_checked = True 。

为什么要分开任务?因为这种恶意软件检查可能是一个漫长的操作。

于 2013-01-10T18:45:58.583 回答