Tôi đang cố gắng tìm ra cách hạn chế quyền truy cập vào thư mục phương tiện trong cấu hình apache của mình. Thư mục tải lên từ một trang web Django và tải lên hình ảnh/pdf được hiển thị trong trang web cho người dùng được xác thực. Vấn đề là, bất kỳ schmo không được xác thực nào cũng có thể điều hướng đến mysite.com/media/images/pic1.jpg
. Điều này không thể xảy ra; Tôi đã thử một số cách để hạn chế hành vi này, nhưng tôi nghĩ rằng tôi cần một hoặc hai gợi ý.
lần thử đầu tiên: XSendfile
Xsendfile dường như hoạt động, nhưng nó (như tên gợi ý) gửi tệp để tải xuống, sau đó trang của tôi được cho là hiển thị hình ảnh không tải. Vì vậy, có vẻ như đây không phải là thứ tôi cần cho ca sử dụng của mình.
lần thử thứ hai: viết lại quy tắc
Tôi đã thêm một số quy tắc viết lại vào cấu hình apache:
RewriteCond "%{HTTP_REFERER}" "!^$"
RewriteCond "%{HTTP_REFERER}" "!mysite.com/priv/" [NC]
RewriteRule "\.(gif|jpg|png|pdf)$" "-" [F,NC]
Tất cả các phần của trang web yêu cầu xác thực đều nằm sau /riêng tư/
đường dẫn, vì vậy ý tưởng của tôi là nếu điều này hoạt động thì điều hướng đến /media/hình ảnh/pic1.jpg
sẽ được viết lại. Nhưng điều này cũng không làm việc mysite.com/media/images/pic1.jpg
vẫn hiển thị hình ảnh.
thử thứ ba: môi trường
Tôi đã thử một cái gì đó tương tự với môi trường bên trong máy chủ ảo:
<VirtualHost *:80>
...
SetEnvIf Referer "mysite\.com\/priv" localreferer
SetEnvIf Referer ^$ localreferer
<FilesMatch "\.(jpg|png|gif|pdf)$">
Require env localreferer
</FilesMatch>
...
</VirtualHost>
Nhưng điều này cũng không hiệu quả; Tôi vẫn có thể điều hướng trực tiếp đến hình ảnh.
lần thử thứ tư: Yêu cầu người dùng hợp lệ
Tôi đã thêm Yêu cầu người dùng hợp lệ
đến v-host, nhưng tôi không thể tìm ra cách kiểm tra nó dựa trên mô hình người dùng Django. Điều này sau thay đổi này, tôi sẽ nhận được lời nhắc đăng nhập mỗi khi tôi tải một trang hiển thị hình ảnh (nhưng không có htaccess, v.v., không có gì để xác thực và không có hình ảnh nào được hiển thị trên trang web.
Sau đó tôi đã cố gắng thực hiện những gì được mô tả ở đây (https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/apache-auth/), nhưng dự án django của tôi không thích Trình xử lý WSGI
(ngược lại với mặc định get_wsgi_application()
). tôi nhận được một nâng cao AppRegistryNotReady("Ứng dụng chưa được tải.")
lỗi. Có vẻ như đây có thể là cách tiếp cận hợp lý nhất, nhưng tôi không biết cách lấy Trình xử lý WSGI
làm việc, hoặc cách tiếp cận làm việc với get_wsgi_application()
.
Tôi biết rằng tôi có thể đặt cho các tệp một tên giống như uuid khó đoán, nhưng đây có vẻ là một giải pháp nửa vời. Vì vậy, chiến lược tốt nhất của tôi là gì để hạn chế quyền truy cập vào thư mục phương tiện để những hình ảnh này chỉ được liên kết trong một phần của trang nơi người dùng được xác thực?
Ubuntu 20.04, Apache 2.4
| Chỉnh sửa, làm theo một số lời khuyên |
auth.py
def check_password(môi trường, tên người dùng, mật khẩu):
print("---->>>---->>>---->>>---->>>---->>> check_password() đã được gọi <<<--- -<<<----<<<----<<<----<<<----")
trả về Đúng
#từ django.contrib.auth.handlers.modwsgi nhập check_password
Nhật ký Apache cho thấy rằng tập lệnh này đã được tải, nhưng chức năng dường như không được thực thi vì câu lệnh in không xuất hiện trong nhật ký. Tôi đặt một câu lệnh in lạc trong tệp này và trong tệp wsgi.py để đảm bảo chiến lược này được đưa vào nhật ký, chỉ chiến lược trong tệp wsgi.py mới được đưa vào nhật ký.
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>
|chỉnh sửa khác |
Tôi chấp nhận câu trả lời vì mọi thứ hiện đang hoạt động. Có rất nhiều bộ phận chuyển động, gây ra vấn đề ban đầu với câu trả lời.
(1) Hàm kiểm tra check_password không hiển thị trong nhật ký apache...à nó xuất hiện lúc /var/log/Apache2/error.log
thay vì nhật ký tùy chỉnh đã được thiết lập. Không chắc tại sao, nhưng ok ...
(2) Venv của tôi không được kích hoạt đúng cách và tôi thực sự không nhận thấy điều này vì django cũng được cài đặt trên hệ thống Python. tôi đã sao chép activate_this.py
tập lệnh từ virtualenv và thêm nó vào venv của tôi và thêm sth như thế này vào tệp wsgi của tôi
activate_this = '/path/to/ENV/bin/activate_this.py'
với open(activ_this) như f:
exec(f.read(), {'__file__': activate_this})
Với những điều đó đã được khắc phục, chức năng check_password hoạt động khi được gọi từ tệp wsgi.py. "hoạt động" ở đây có nghĩa là nó hạn chế quyền truy cập vào thư mục mà người dùng chưa được xác thực không có quyền truy cập. Người dùng vẫn cần cung cấp thông tin xác thực hai lần - một lần trong chế độ xem django thông thường và một lần trong lời nhắc của trình duyệt. Điều này thật khó chịu, nhưng thực ra câu hỏi của tôi là về việc hạn chế quyền truy cập, vì vậy tôi sẽ để nó vào một ngày khác.
Đề xuất của câu trả lời để gọi check_password từ auth.py không hợp tác với dự án của tôi. Tôi gặp lỗi cho thấy nó được gọi trước wsgi.py – có vẻ như venv chưa được tải hoặc cài đặt chưa được tải tại thời điểm check_password được gọi.