您的评论:
这里的 whitenoise 文档说我们不应该同时使用这两个中间件,我只是想知道在 django.security 上使用 whitenoise 是否有缺点 – Manan Mehta 30 分钟前
不,它没有这么说 - 文档的那部分是指 MIDDLEWARE_CLASSES 的顺序。您可以愉快地将 Whitenoise 与 Django 的安全中间件一起使用。
摘自以下文档:
编辑您的 settings.py 文件并将 WhiteNoise 添加到 MIDDLEWARE_CLASSES 列表中,高于除 Django 的 SecurityMiddleware 之外的所有其他中间件:
MIDDLEWARE_CLASSES = [
# 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]
SnakeFcz 建议强制 Django 提供静态服务并不是一个好主意 - Whitenoise 包被设计为通过 Django 提供静态服务的高性能方法。请参阅 heroku docs 和 Whitenoise docs。
回复您的编辑:
在 Django 中,静态是指您在开发过程中创建的 JS/CSS/图像等在部署应用时不会更改(保持静态)的内容。媒体是用户上传的图片和视频,或生成的图片(例如缩略图)。
Django 建议将静态和媒体分别存储在 STATIC_ROOT 和 MEDIA_ROOT 目录中。然后在生产中,您通常会在这些目录中为 URL STATIC_URL 和 MEDIA_URL 配置 Web 服务器。 Whitenoise 通过正确地从这些文件夹中提供文件来简化事情,而无需配置 Web 服务器。
让 Django 正确提供图像(静态或媒体)的主要问题如下:
还有一些 Whitenoise 可能无法处理的标头,具体取决于您返回图像的方式:
媒体类型 - 浏览器需要知道如何处理它们收到的响应,因此有一个名为 Content-Type 的标头。使用上面的代码,您将每个文件都作为图像返回 - 如果用户要求 PNG 怎么办?
内容长度 - 浏览器使用内容长度(响应的大小)来显示进度条,并进行其他优化(例如以块的形式读取响应)。
-
压缩 - 大多数浏览器和网络服务器(和 Whitenoise)都支持压缩方法,例如 gzip 或最近的 brotli(由 google 构建)。 Web 服务器会压缩文件(通常是一次,然后将压缩文件缓存起来)以最小化传输过程中的带宽。根据图像和格式,您通常可以将图像压缩到其大小的 60-70% 左右。
lena 位图上的演示:
❯ brew install gzip brotli
❯ gzip -k -v lena.bmp
lena.bmp: 18.3% -- replaced with lena.bmp.gz
❯ bro --input lena.bmp --output lena.bmp.bro
❯ ls -lh lena*
-rw-r--r--@ 1 alex staff 768K Feb 16 21:41 lena.bmp
-rw------- 1 alex staff 527K Feb 16 21:45 lena.bmp.bro
-rw-r--r--@ 1 alex staff 627K Feb 16 21:41 lena.bmp.gz
-
安全性 - 将静态资产留给 Web 服务器的另一个原因是潜在的安全漏洞!
假设您的视图中提供图片的代码如下,并且 URL 设置为static/<filename>。
img = os.path.join(settings.MEDIA_ROOT, filename)
with open(img, "rb") as f:
return HttpResponse(f.read(), content_type="image/jpeg")
想象一下,如果恶意用户导航到yoursite.com/static//Users/alex/.ssh/id_rsa。然后文件名变成/Users/alex/.ssh/id_rsa:
filename = '/Users/alex/.ssh/id_rsa'
os.path.join(settings.MEDIA_ROOT, filename)
# '/Users/alex/.ssh/id_rsa'
然后视图读取您的网络服务器的私钥,并将其返回给恶意用户。哎呀!现在他们可以通过 ssh 进入您的服务器。
Heroku 上的媒体:
如果您要部署到 Heroku,要记住的一件事是他们的 dynos 的工作方式。 Heroku dynos 经常被创建和销毁(每次部署时,至少每天),因此您不能依赖文件系统留下来。您还可以一次运行两个或多个测功机——它们是完全独立的容器,在数据中心的不同主机上运行,它们不共享文件系统。通常,如果您想处理用户上传的媒体,您将使用Django-storages 将图像存储在 S3(AWS 的存储服务)而不是文件系统上。您也可以将图像存储在数据库中,但这不能很好地扩展。有关设置为在 S3 上存储媒体的示例 Django 应用程序,请参阅 https://github.com/eknuth/django-heroku-s3-bootstrap-demo。