2

我使用python中的requests库通过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 类型真的是服务器所说的?)有没有更好的方法来编写安全下载例程?

4

1 回答 1

3

您的代码的潜在安全风险取决于您对所联系服务器的信任程度。如果你确定服务器永远不会用一些恶意内容来欺骗你,那么你使用那段代码是相对安全的。否则,请自行检查内容类型。最大的潜在风险可能是在不知不觉中保存可执行文件而不是图像。一个较小的可能是存储一种不同类型的内容,这些内容可能会使 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 有很好的文档,所以如果你考虑使用它,我建议你看看他们的 README。

于 2017-03-27T14:58:22.887 回答