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



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

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

最新更新