图像下载mime类型验证python请求

时间:2017-03-27 13:41:41

标签: python python-3.x python-requests python-imaging-library bytesio

我使用python中的请求库通过http下载大量图像文件。我在python中使用BytesIO将接收的内容转换为原始字节,然后使用Pillow()将此原始内容保存为jpeg文件。

from PIL import Image
from io import BytesIO

rsp = requests.get(imageurl)
content_type_received = rsp.headers['Content-Type'] # mime type
binarycontent = BytesIO(rsp.content)
if content_type_received.startswith('image'): # image/jpeg, image/png etc
    i = Image.open(binarycontent)
    outfilename = os.path.join(outfolder,'myimg'+'.jpg')
    with open(outfilename, 'wb') as f:
        f.write(rsp.content)
    rsp.close()

此代码的潜在安全风险是什么? (我不确定我们能够相信服务器在响应头中说mime类型真的是服务器所说的那么多吗?)有没有更好的方法来编写安全下载例程?

1 个答案:

答案 0 :(得分:1)

代码的潜在安全风险取决于您对服务器的信任程度。 如果您确定服务器永远不会试图欺骗您使用某些恶意内容,那么您使用该代码就相对安全了。 否则,请自行检查内容类型。 最大的潜在风险可能是在不知不觉中保存可执行文件而不是图像。 较小的一个可能是存储可能导致PIL或应用程序中的其他组件崩溃的不同类型的内容。

请记住,服务器可以自由选择任何响应标头所需的值,包括内容类型。 如果您有任何理由相信您与之联系的服务器可能不诚实,那么您就不应该信任请求标头。

如果您想要一种更可靠的方法来确定收到的内容的内容类型,我建议您查看python-magic,libmagic的包装器。 这个图书馆将帮助您确定自己的内容类型,因此您不必信任"信任"您要从中下载的服务器。

# ...
content = BytesIO(rsp.content)
mime = magic.from_buffer(content.read(1024), mime=True)
if mime.startswith('image'):
    content.seek(0) # Reset the bytes stream position because you read from it
    # ...

python-magic有很好的文档记录,所以如果您考虑使用它,我建议您查看自述文件。