Как вам требуется логин для медиафайлов в Django? - PullRequest
26 голосов
/ 12 июля 2009

Я размещаю «конфиденциальную» информацию в загружаемых PDF-файлах и таблицах в разделе регистрации пользователей сайта.

Есть ли способ разрешить аутентификацию django для защиты этого носителя без его обслуживания (и не нужно вручную входить в систему с использованием базовой аутентификации)?

Я предполагаю, что есть (скрестив пальцы) не способ сделать это с помощью приведенного ниже кода псевдо, но это помогает лучше проиллюстрировать конечную цель.

#urls.py
(r'^protected_media/(?P<filename>.*)$', 'protected_media')

#views.py
from django.contrib.auth.decorators import login_required

@login_required
def protected_media(request, filename):
    # @login_required bounces you out to the login url
    # if logged in, serve "filename" from Apache

Ответы [ 4 ]

9 голосов
/ 12 июля 2009

Мне кажется, что метод, который вы описали в своем коде, должен работать. Он действительно ничем не отличается от любого другого защищенного ресурса: ваши представления могут обслуживать файлы с дисков, записи из баз данных, визуализированные шаблоны или что-либо еще. Так же, как декоратор login_required предотвращает несанкционированный доступ к другим представлениям, он предотвращает такой доступ к вашему представлению, обслуживающему защищенные носители.

Я что-то упустил из вашего вопроса здесь? Пожалуйста, уточните, если это так.

РЕДАКТИРОВАТЬ: Что касается ссылки django doc в вашем комментарии: это метод простого обслуживания любого файла запроса из определенного каталога. Таким образом, в этом примере URL-адреса, такие как /site_media/foo.jpg, /site_media/somefolder/bar.jpg будут автоматически искать файлы foo.jpg и somefolder/bar.jpg в document_root. По сути, каждая вещь в document_root будет общедоступной. Это явно небезопасно. Таким образом, вы избегаете этого своим методом.

Это также считается неэффективным, потому что django просто добавляет много ненужных накладных расходов, когда все, что вам нужно, это что-то вроде Apache, чтобы принять запрос URL и сопоставить его с файлом на жестком диске. (Вам не нужны сессии django, обработка запросов и т. Д.)

В вашем случае это может быть не такой большой проблемой. Во-первых, вы обеспечили вид. Во-вторых, это зависит от ваших моделей использования. Сколько запросов вы ожидаете для этих файлов? Вы используете только django для аутентификации - это оправдывает другие издержки? Если нет, вы можете посмотреть, как эти файлы обслуживать Apache и использовать поставщика аутентификации. Подробнее об этом см. Документацию mod_wsgi:

Есть аналогичные механизмы, доступные под mod_python Я полагаю. (Обновление: только что заметил другой ответ. Пожалуйста, смотрите ответ Андре для метода mod_python.)

РЕДАКТИРОВАТЬ 2: Что касается кода для передачи файла, пожалуйста, посмотрите этот фрагмент:

Метод send_file использует FileWrapper, который хорош для отправки больших статических файлов обратно (он не читает весь файл в память). Вам нужно будет изменить content_type в зависимости от типа отправляемого файла (pdf, jpg и т. Д.).

4 голосов
/ 07 декабря 2010

Прочтите это Билет Django для получения дополнительной информации. Начните с нижней части, чтобы сэкономить время. Похоже, что только что пропустил в Django 1.2, и я полагаю, что не в 1.3.

Для Nginx я нашел этот фрагмент Django , который использует преимущества заголовка X-Accel-Redirect, но еще не пробовал.

3 голосов
/ 12 июля 2009

Более эффективная подача статических файлов через Django в настоящее время рассматривается как часть проекта Google SOC. Для WSGI это будет использовать расширения wsgi.file_wrapper для WSGI, если они доступны, как и для mod_wsgi, и req.sendfile (), если используется mod_python. Он также будет поддерживать возврат заголовков, таких как «Местоположение», «X-Accel-Redirect» и других, которые различные механизмы веб-хостинга и внешние прокси-серверы принимают в качестве средства для обслуживания статических файлов, местоположение которых определяется внутренним веб-приложением. , который не так эффективен, как интерфейс для обслуживания статических файлов.

Я не уверен, есть ли где-нибудь страница проекта для этого в вики Django или нет, но изменения кода фиксируются в ветке веток / soc2009 / http-wsgi-улучшений репозитория исходного кода Django.

Тебе не нужно строго ждать этого. Это просто создание чистого и портативного интерфейса между различными механизмами. Если вы используете nginx в качестве внешнего интерфейса перед Apache / mod_wsgi, вы можете использовать X-Accel-Redirect сейчас. Если вы используете Apache / mod_wsgi 3.0 и режим демона, вы можете использовать Location сейчас, но вам нужно убедиться, что вы правильно настроили Apache. В качестве альтернативы вы могли бы реализовать свою собственную промежуточную программную оболочку WSGI вокруг приложения Django, которая ищет свой собственный заголовок ответа, чтобы указать файл, который должен быть возвращен, и который использует wsgi.file_wrapper, чтобы вернуть его вместо фактического ответа, возвращенного из Django.

Кстати, механизмы перехвата аутентификации, перечисленные как для mod_python, так и для mod_wsgi другими, будут использовать базовую аутентификацию HTTP, а это не то, что вам нужно. Предполагается, что вы хотите, чтобы файлы были защищены механизмом входа в систему на основе форм Django с использованием файлов cookie и внутренних сеансов.

1 голос
/ 12 июля 2009

Если я правильно понимаю ваш вопрос, вы хотите ограничить доступ к файлам, которые не обслуживаются Django, например, с сервера Apache?

В таком случае вам потребуется, чтобы сервер Apache использовал Django в качестве источника аутентификации.

Этот фрагмент django описывает такой метод. Он создает обработчик доступа в Django, который используется Apache, когда поступает запрос на статический файл, который необходимо защитить:

<Location "/protected/location">
            PythonPath "['/path/to/proj/'] + sys.path"  
            PythonOption DJANGO_SETTINGS_MODULE myproj.settings
        PythonOption DjangoPermissionName '<permission.codename>'
        PythonAccessHandler my_proj.modpython #this should point to accesshandler
            SetHandler None
</Location>

Надеюсь, это поможет, фрагмент был опубликован некоторое время назад, поэтому между версиями Django все могло измениться:)

...