限制对 Django/Nginx 中静态文件的访问

问题描述 投票:0回答:4

我正在构建一个系统,允许用户生成文档然后下载它们。这些文档是 PDF(对于这个问题来说这并不重要),当它们生成时,我将它们存储在 Web 服务器运行的本地文件系统上,文件名是 uuid

c7d43358-7532-4812-b828-b10b26694f0f.pdf

但我知道“通过默默无闻的安全”不是正确的解决方案......

如果可能的话,我想限制对每个帐户的文件的访问。我认为我可以做的一件事是将它们上传到 S3 并提供签名 URL,但如果可能的话,我现在想避免这样做。

我正在使用 Nginx/Django/Gunicorn/EC2/S3

还有哪些其他解决方案?

django security nginx
4个回答
10
投票

如果您提供小文件,您确实可以使用 Django 直接提供它们,将文件写入

HttpResponse
对象。

但是,如果您要提供大文件,您可能希望将该任务留给您的网络服务器,您可以使用 Nginx 上的

X-Accel-Redirect
标头(以及 Apache 和 Lighttpd 的
X-Sendfile
)让您的网络服务器为您提供文件.

您可以在此处在 Nginx 文档中找到有关标头本身的更多信息,并且您可以在此处找到有关如何在 Django 中使用标头的一些灵感

完成通过 Django 视图发送文件后,使用 Django 的身份验证框架强制执行用户身份验证应该非常简单。


3
投票

如何在视图级别强制执行

user==owner
,防止访问文件,将它们存储为 FileFields,并且仅在满足该条件时检索文件。

例如您可以在视图上使用

@login_required
decorator 仅在登录时才允许访问。这可以使用
request.user
进行细化以检查文件的所有者。 Django 文档 的用户身份验证部分可能会有所帮助。

正如您提到的,另一个选项是通过 S3 本身,在 Django 中生成 url,其中包含一个查询字符串,允许经过身份验证的用户访问以下载具有时间限制的特定 s3 对象。有关详细信息,请参阅s3 文档。之前曾在here on SO.

提出过类似的问题。

2
投票

我使用 django-private-files 取得了巨大成功,它在视图级别强制实施保护,并使用不同的后端来进行实际的文件传输。


0
投票

要在使用 Nginx 提供文件时管理 Django 应用程序中的用户对静态文件的访问,您可以实现一个安全系统来控制访问。这是解决此问题的分步方法:

  1. 使用 Nginx 保护静态文件

首先,配置Nginx以限制对静态文件的直接访问。这可以通过使用 Nginx 中的内部重定向和访问控制来完成。

编辑 Nginx 配置文件(例如 /etc/nginx/sites-available/your_site):

nginx

server {
    listen 80;
    server_name your_domain.com;

    location /static/ {
        internal;
        alias /path/to/staticfiles/;
    }

    location /media/ {
        internal;
        alias /path/to/mediafiles/;
    }

    location /protected_static/ {
        alias /path/to/staticfiles/;
        add_header X-Accel-Redirect /static/;
    }

    location /protected_media/ {
        alias /path/to/mediafiles/;
        add_header X-Accel-Redirect /media/;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

在此配置中:

/static/ 和 /media/ 位置被标记为内部,这意味着它们不能直接从外部访问。 /protected_static/ 和 /protected_media/ 位置充当这些内部位置的代理,添加 X-Accel-Redirect 标头以执行内部重定向。

  1. 使用 Django 保护 URL

在 Django 中,创建一个视图,在提供静态文件之前检查用户权限。该视图将生成 Nginx 可以处理的 URL。

from django.http import HttpResponse, Http404
from django.conf import settings
import os

def serve_protected_file(request, file_path):
    # Check user permissions here
    if not request.user.is_authenticated:
        raise Http404

    # Generate the X-Accel-Redirect header
    response = HttpResponse()
    response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(file_path)
    response['X-Accel-Redirect'] = os.path.join('/protected_static/', file_path)
    response['Content-Type'] = ''

    return response
  1. 更新网址

更新您的 urls.py 以指向新视图:

from django.urls import path
from . import views

urlpatterns = [
    path('protected_static/<path:file_path>/', views.serve_protected_file, name='serve_protected_file'),
]
  1. 在模板中使用安全 URL

在您的模板中,使用安全 URL:

<a href="{% url 'serve_protected_file' file_path='path/to/your/file.jpg' %}">Download</a>
  1. 额外安全措施

    基于令牌的访问:为了提高安全性,生成在一定时间后过期的临时访问令牌。 日志记录和监控:记录对受保护文件的访问并监控异常活动。

遵循这些步骤可确保静态文件受到保护并且只有授权用户才能访问。 Nginx 的内部重定向和 Django 的权限检查的结合使您可以安全地管理用户对 URL 的访问。

© www.soinside.com 2019 - 2024. All rights reserved.