我有一个 Django Rest 框架应用程序在安全的 Nginx 服务器上运行。 当我在 DRF API 上导航时,导航栏中的协议会很好地重定向到 https。 我的问题是所有生成的 URL 都是 http 而不是 https。 我在代码中看到,不同的URL都是用这个方法构建的:
def build_absolute_uri(self, location=None):
"""
Build an absolute URI from the location and the variables available in
this request. If no ``location`` is specified, build the absolute URI
using request.get_full_path(). If the location is absolute, convert it
to an RFC 3987 compliant URI and return it. If location is relative or
is scheme-relative (i.e., ``//example.com/``), urljoin() it to a base
URL constructed from the request variables.
"""
if location is None:
# Make it an absolute URL (but schemeless and domainless) for the
# edge case that the path starts with '//'.
location = '//%s' % self.get_full_path()
bits = urlsplit(location)
if not (bits.scheme and bits.netloc):
current_uri = '{scheme}://{host}{path}'.format(scheme=self.scheme,
host=self.get_host(),
path=self.path)
# Join the constructed URL with the provided location, which will
# allow the provided ``location`` to apply query strings to the
# base path as well as override the host, if it begins with //
location = urljoin(current_uri, location)
return iri_to_uri(location)
就我而言,此方法始终返回不安全的 URL(HTTP 而不是 HTTPS)。 我已经按照这篇文章中的描述编辑了我的设置: https://security.stackexchange.com/questions/8964/trying-to-make-a-django-based-site-use-https-only-not-sure-if-its-secure 但生成的 URL 仍然是 HTTP。 这是我的 Nginx 配置:
server {
listen 80;
listen [::]:80;
server_name backend.domaine.na.me www.backend.domaine.na.me server_ip:8800;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-backend.domaine.na.me.conf;
include snippets/ssl-params.conf;
location / {
proxy_pass http://server_ip:8800/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
server {
listen 8800;
server_name server_ip;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /projects/my_django_app;
}
location /media/ {
root /projects/my_django_app;
}
location / {
include proxy_params;
proxy_pass http://unix:/projects/my_django_app.sock;
}
location ~ /.well-known {
allow all;
}
}
还有我的 Django 配置:
在
wsgi.py
:
os.environ['HTTPS'] = "on"
os.environ['wsgi.url_scheme'] = "https"
在
settings.py
(注意:我已经尝试了前两行):
#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_PROXY_SSL_HEADER = ('HTTP_X_SCHEME', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
我真的需要解决这个问题,因为我的 DRF API 返回一些图像 URL,该 URL 必须是 HTTPS,否则该网站不能被视为 100% 安全。
我的配置有什么问题吗?我是否缺少一些选项?
不需要间接;您可以合并 SSL 块和 :8800 块中的设置,得到如下所示的内容:
server {
listen 80;
listen [::]:80;
server_name backend.domaine.na.me www.backend.domaine.na.me;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-backend.domaine.na.me.conf;
include snippets/ssl-params.conf;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /projects/my_django_app;
}
location /media/ {
root /projects/my_django_app;
}
location ~ /.well-known {
allow all;
}
location / {
proxy_pass http://unix:/projects/my_django_app.sock;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
然后,设置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
,它应该可以工作。
我找不到任何有关
include proxy_params
的信息,我怀疑您在第一个代理块中设置的标头根本没有转发到 Django 应用程序。