Puncte:1

Apache: restricționați difuzarea imaginilor la utilizatorii autentificați

drapel cn
Bob

Î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.

Puncte:1
drapel ve

asta este ceea ce face get_wsgi_application:

def get_wsgi_application():
    django.setup(set_prefix=False) # aceasta va duce la „apps_ready=true”
    returnează WSGIHandler()

este configurarea mediului django înainte de a returna handler-ul.

Următoarele ar trebui să facă truc în wsgi.py:

aplicație = get_wsgi_application()
din django.contrib.auth.handlers.modwsgi import check_password
# succesiunea este importanta!!

De fapt, problema este prima linie din modwsgi.py:

UserModel = auth.get_user_model()

deoarece get_user_model() va verifica dacă apps_ready și tot ce se face în momentul în care python execută importul fișierului!

cea mai bună modalitate ar fi să creați un auth.py separat și să verificați mai întâi dacă este într-adevăr apelat de Apache cu o imprimare simplă care va merge la error.log al Apache:

def check_password(mediu, nume de utilizator, parolă):
    print("************ check_password() a fost numit ********")
    returnează Adevărat

Odată ce rulează, îl puteți înlocui cu instrucțiunea de import și utilizați djangos check_password().

din django.contrib.auth.handlers.modwsgi import check_password

Apoi ceva de genul următor în httpd-vhosts.conf:

<VirtualHost *:80>

   ....

   <Directory path_to_server_root/secret>
        AuthType Basic
        AuthName "Top Secret"
        AuthBasicProvider wsgi
        WSGIAuthUserScript path_to_wsgi/wsgi.py
        Require valid-user
   </Directory>

</VirtualHost>
drapel cn
Bob
Mulțumiri! Două lucruri ciudate se întâmplă după implementarea modificărilor pe care le sugerați. 1. Primesc din browser o solicitare de autentificare (doar prima dată, dar îmi imaginez că ar trebui să se ocupe de vizualizarea mea de conectare). 2. Nu sunt afișate imagini din folderul secret â site-ul se încarcă, dar solicitarea img returnează o eroare 500 („faza de autentificare „verificare utilizator” a dat starea 500” în fișierele jurnal.) Nu știu ce înseamnă & google nu este de ajutor.
Razenstein avatar
drapel ve
Schimb răspunsul de mai sus: creează un fișier separat „auth.py” (care este oricum lucrul corect de făcut și nu îl amestec cu standardul wsgi.py - am vrut doar să-l păstrez simplu în primul răspuns) și pune un funcția de testare în - atunci puteți vedea dacă Apache vă apelează funcția „check_password”.
Razenstein avatar
drapel ve
dacă doriți să afișați de ex. o imagine din interiorul unei pagini, folosește XSendfile așa cum menționezi ca soluție (1) - funcționează. În funcția/vizualizarea care servește URL-ul XSendfile puteți restricționa accesul la fel cum ați restricționa accesul la orice altă vizualizare. Și prin activarea XSendFile în Apache, orice acces la directorul respectiv va fi direcționat către aplicația dvs. django.
drapel cn
Bob
Și când apache nu apelează funcția în auth.py, ce atunci? Trebuie să-l import cumva? Sau faceți referire la el în configurația apache cumva? Jurnalele de erori sunt aceleași cu primul răspuns.
Razenstein avatar
drapel ve
verificați dacă directiva „WSGIAuthUserScript path_to_auth_script/auth.py” este corectă. Postați httpd-vhost.conf și auth.py .
drapel cn
Bob
postat în editare
drapel cn
Bob
Începând de acum, folderul privat este ascuns utilizatorilor neautentificați, dar utilizatorul trebuie să se autentifice prin intermediul promptului din browser după ce se conectează deja la site prin vizualizări obișnuite de auth django. Apache nu îmi apelează scriptul auth.py, așa că presupun că a face ca acest lucru să funcționeze va rezolva autentificarea suplimentară.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.