Încerc să găsesc o modalitate de a restricționa accesul la un folder media din configurația mea Apache. Dosarul preia încărcări de pe un site Django, iar încărcările de imagini/pdf sunt afișate pe site pentru utilizatorii autentificați. Problema este că orice schmo neautentificat poate naviga mysite.com/media/images/pic1.jpg
. Acest lucru nu ar trebui să fie posibil; Am încercat câteva lucruri pentru a restricționa acest comportament, dar cred că am nevoie de un indiciu sau două.
prima încercare: XSendfile
Xsendfile părea să funcționeze, dar (după cum sugerează și numele) trimite fișierul pentru descărcare, apoi pagina mea care ar trebui să afișeze imagini nu se încarcă. Deci, se pare că nu este ceea ce am nevoie pentru cazul meu de utilizare.
a doua încercare: regulă de rescrie
Am adăugat câteva reguli de rescriere la configurația apache:
RewriteCond „%{HTTP_REFERER}” „!^$”
RewriteCond „%{HTTP_REFERER}” „!mysite.com/priv/” [NC]
RewriteRule "\.(gif|jpg|png|pdf)$" "-" [F,NC]
Toate părțile site-ului care necesită autentificare se află în spatele /priv/
cale, deci ideea mea a fost că, dacă funcționează, atunci navigați la /media/images/pic1.jpg
ar fi rescris. Dar nici asta nu a funcționat mysite.com/media/images/pic1.jpg
încă arată imaginea.
a treia încercare: mediu
Am încercat ceva similar cu un mediu din interiorul virtualhost:
<VirtualHost *:80>
...
SetEnvIf Referer "mysite\.com\/priv" localreferer
SetEnvIf Referer ^$ localreferer
<FilesMatch "\.(jpg|png|gif|pdf)$">
Require env localreferer
</FilesMatch>
...
</VirtualHost>
Dar nici asta nu a funcționat; Încă pot naviga direct la imagine.
a patra încercare: necesită un utilizator valid
Am adăugat Necesită utilizator valid
la v-gazdă, dar nu îmi pot da seama cum să-l verific cu modelul de utilizator Django. Acest lucru, după această modificare, aș primi o solicitare de conectare de fiecare dată când încărcam o pagină care afișează imagini (dar fără htaccess etc., nu există nimic împotriva căruia să se autentifice și nicio imagine nu este afișată pe site.
Apoi am încercat să implementez ceea ce este descris aici (https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/apache-auth/), dar proiectul meu django nu-i place WSGIHandler
(spre deosebire de cea implicită get_wsgi_application()
). primesc un raise AppRegistryNotReady ("Aplicațiile nu sunt încă încărcate.")
eroare. Se pare că aceasta ar putea fi cea mai rezonabilă abordare, dar nu știu cum să obțin WSGIHandler
de lucru, sau abordarea de lucru cu get_wsgi_application()
.
Sunt conștient că aș putea da fișierelor un nume de tip uuid greu de ghicit, dar aceasta pare o soluție pe jumătate. Deci, care este cea mai bună strategie a mea de a restricționa accesul la folderul media, astfel încât aceste imagini să fie conectate doar în partea din site-ul în care utilizatorii sunt autentificați?
Ubuntu 20.04, Apache 2.4
| Editează, urmând câteva sfaturi |
auth.py
def check_password(mediu, nume de utilizator, parolă):
print("---->>>---->>>---->>>---->>>---->>> check_password() a fost numit <<<--- -<<<----<<<----<<<----<<<----")
returnează Adevărat
#de la django.contrib.auth.handlers.modwsgi import check_password
Jurnalele Apache arată că acest script este încărcat, dar funcția aparent nu este executată, deoarece instrucțiunea print nu apare în jurnale. Am pus o declarație de tipărire rătăcită în acest fișier și în fișierul wsgi.py pentru a mă asigura că această strategie ajunge în jurnal, doar ceea ce era în fișierul wsgi.py a ajuns în jurnal.
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>
|o altă modificare |
Am acceptat răspunsul pentru că totul este acum funcțional. Au fost o mulțime de piese în mișcare, ceea ce a cauzat problema inițială cu răspunsul.
(1) Funcția test check_password nu apărea în jurnalele Apache... ei bine, apărea la /var/log/apache2/error.log
în loc de jurnalele personalizate care au fost configurate. Nu stiu de ce, dar ok...
(2) Venv-ul meu nu a fost activat corect și de fapt nu am observat acest lucru deoarece django este instalat și pe sistemul Python. Am copiat activate_this.py
script de la un virtualenv și l-am adăugat la venv-ul meu și am adăugat sth ca acesta la fișierul meu wsgi
activate_this = '/path/to/ENV/bin/activate_this.py'
cu open(activate_this) ca f:
exec(f.read(), {'__file__': activate_this})
Cu aceste lucruri remediate, funcția check_password funcționează atunci când este apelată din fișierul wsgi.py. „funcționează” aici înseamnă că restricționează accesul la folderul la care utilizatorii neautentificați nu ar trebui să aibă acces. Utilizatorii mai trebuie să furnizeze acreditările de două ori – o dată în vizualizarea obișnuită django și o dată în promptul browserului. Acest lucru este iritant, dar de fapt întrebarea mea a fost despre restricționarea accesului, așa că o voi lăsa pentru altă zi.
Sugestia răspunsului de a apela check_password de la auth.py nu cooperează cu proiectul meu. Primesc erori care sugerează că este apelat înainte de wsgi.py â se pare că venv nu este încărcat sau setările nu sunt încărcate în momentul în care este apelat check_password.