Я пытаюсь найти способ ограничить доступ к папке мультимедиа в моей конфигурации apache. Папка принимает загрузки с сайта Django, а загрузки изображений/pdf отображаются на сайте для аутентифицированных пользователей. Проблема в том, что любой неаутентифицированный schmo может перейти к mysite.com/media/images/pic1.jpg
. Это не должно быть возможным; Я пробовал несколько вещей, чтобы ограничить это поведение, но я думаю, что мне нужен указатель или два.
первая попытка: XSendfile
Xsendfile, похоже, работает, но он (как следует из названия) отправляет файл для загрузки, тогда моя страница, которая должна отображать изображения, не загружается. Так что, похоже, это не то, что мне нужно для моего варианта использования.
вторая попытка: переписать правило
Я добавил некоторые правила перезаписи в конфигурацию apache:
RewriteCond "%{HTTP_REFERER}" "!^$"
RewriteCond "%{HTTP_REFERER}" "!mysite.com/priv/" [NC]
RewriteRule "\.(gif|jpg|png|pdf)$" "-" [F,NC]
Все части сайта, требующие аутентификации, находятся за /приват/
путь, поэтому моя идея заключалась в том, что если это сработает, то переход к /медиа/изображения/pic1.jpg
был бы переписан. Но и это не сработало mysite.com/media/images/pic1.jpg
все еще показывает изображение.
третья попытка: окружающая среда
Я пробовал что-то подобное со средой внутри виртуального хоста:
<VirtualHost *:80>
...
SetEnvIf Referer "mysite\.com\/priv" localreferer
SetEnvIf Referer ^$ localreferer
<FilesMatch "\.(jpg|png|gif|pdf)$">
Require env localreferer
</FilesMatch>
...
</VirtualHost>
Но это тоже не сработало; Я все еще могу перейти непосредственно к изображению.
четвертая попытка: Требовать действительного пользователя
я добавил Требовать действительного пользователя
на v-host, но я не могу понять, как проверить его на пользовательскую модель Django. Это после этого изменения, я буду получать приглашение войти в систему каждый раз, когда я загружаю страницу, которая отображает изображения (но без htaccess и т. д., нет ничего для аутентификации, и изображения не отображаются на сайте.
Я то попытался реализовать то, что описано здесь (https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/apache-auth/), но моему проекту django не нравится WSGIHandler
(в отличие от стандартного get_wsgi_application()
). я получаю поднять AppRegistryNotReady("Приложения еще не загружены")
ошибка. Кажется, это может быть наиболее разумным подходом, но я не знаю, как получить WSGIHandler
работает, или подход, работающий с get_wsgi_application()
.
Я знаю, что мог бы дать файлам трудно угадываемое имя, похожее на uuid, но это похоже на половинчатое решение. Итак, какова моя наилучшая стратегия для ограничения доступа к папке мультимедиа, чтобы эти изображения были связаны только в той части сайта, где пользователи аутентифицируются?
Убунту 20.04, Апач 2.4
| Редактировать, следуя некоторым советам |
auth.py
def check_password (окружение, имя пользователя, пароль):
print("---->>>---->>>---->>>---->>>---->>> check_password() была вызвана <<<--- --<<<----<<<----<<<----<<<----")
вернуть Истина
#из django.contrib.auth.handlers.modwsgi import check_password
Журналы Apache показывают, что этот скрипт загружен, но функция, по-видимому, не выполняется, поскольку оператор печати не появляется в журналах. Я поместил блуждающую инструкцию печати в этот файл и в файл wsgi.py, чтобы убедиться, что эта стратегия попала в журналы, только то, что было в файле wsgi.py, попало в журнал.
vhost:
<VirtualHost *:80>
ServerName mysite.com
ServerAlias mysite.com
DocumentRoot /path/to/docroot/
Alias /static/ /path/to/docroot/static/
# Not sure if I need this
Alias /media/ /path/to/docroot/media/
<Directory /path/to/docroot/static/>
Require all granted
</Directory>
<Directory /path/to/docroot/media/>
Require all granted
</Directory>
# this is my restricted access directory
<Directory /path/to/docroot/media/priv/>
AuthType Basic
AuthName "Top Secret"
AuthBasicProvider wsgi
WSGIAuthUserScript /path/to/docroot/mysite/auth.py
Require valid-user
</Directory>
<Directory /path/to/docroot/mysite/>
<Files "wsgi.py">
Require all granted
</Files>
</Directory>
WSGIDaemonProcess open-ancestry-web python-home=/path/to/ENV/ python-path=/path/to/docroot/ processes=10 threads=10
WSGIProcessGroup mysite-pgroup
WSGIScriptAlias / /path/to/docroot/mysite/wsgi.py
LogLevel trace8
ErrorLog "|/bin/rotatelogs -l /path/to/logs/%Y%m%d-%H%M%S_443errors.log 30"
CustomLog "|/bin/rotatelogs -l /path/to/logs/%Y%m%d-%H%M%S_443access.log 30" combined
</VirtualHost>
|другое редактирование |
Я принял ответ, потому что теперь все работает. Было много движущихся частей, что вызвало первоначальную проблему с ответом.
(1) Тестовая функция check_password не отображалась в журналах Apache... ну, она появлялась в /var/журнал/apache2/error.log
вместо настроенных пользовательских журналов. Не знаю почему, но ладно...
(2) Мой venv не был активирован должным образом, и я на самом деле этого не заметил, потому что django также установлен в системе Python. я скопировал activ_this.py
script из virtualenv и добавил его в мой venv и добавил что-то вроде этого в мой файл wsgi
enable_this = '/path/to/ENV/bin/activate_this.py'
с open(activate_this) как f:
exec(f.read(), {'__file__': активировать_это})
Когда эти вещи исправлены, функция check_password работает при вызове из файла wsgi.py. «работает» здесь означает, что он ограничивает доступ к папке, к которой у неаутентифицированных пользователей не должно быть доступа. Пользователям по-прежнему необходимо вводить учетные данные дважды — один раз в обычном представлении django и один раз в приглашении браузера. Это раздражает, но на самом деле мой вопрос был об ограничении доступа, поэтому я оставлю его на другой день.
Предложение ответа вызвать check_password из auth.py не сотрудничает с моим проектом. Я получаю сообщения об ошибках, которые предполагают, что он вызывается до wsgi.py — кажется, что venv не загружен или настройки не загружены во время вызова check_password.