简体   繁体   English

django:使用NGINX的SECURE_SSL_REDIRECT导致应用程序崩溃

[英]django: application crash with SECURE_SSL_REDIRECT using NGINX

I'm trying to make my django app work behind SSL, using nginx, gunicorn; 我正在尝试使用nginx,gunicorn使django应用程序在SSL之后工作; all installed in a server that can be accessed in intranet but not from outside. 所有安装在服务器上的服务器都可以在Intranet中访问,但不能从外部访问。 These are my settings. 这些是我的设置。

settings.py: settings.py:

...
SECURITY_MIDDLEWARE = ('django.middleware.security.SecurityMiddleware',)
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'SAMEORIGIN'
SECURE_HSTS_SECONDS = 60 
SECURE_BROWSER_XSS_FILTER = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')

nginx.conf: nginx.conf:

server {
   listen 80;
   server_name HOSTNAME;

   location / {
       proxy_set_header Host $host;
       proxy_pass http://unix:/tmp/HOSTNAME.socket;
       proxy_set_header X-Forwarded-Protocol $scheme;
       rewrite ^ https://$host/$request_uri permanent;
   }
}

Wondering if someone can point me to the correct solution. 想知道是否有人可以指出正确的解决方案。

disclaimer: I'm new to web development. 免责声明:我是Web开发的新手。 I'm also the author of the question. 我也是问题的作者。

edit : In /var/log/nginx/HOSTNAME_error.log I was getting the following error: 编辑 :在/var/log/nginx/HOSTNAME_error.log中,我得到以下错误:

no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking

Based on Steve's answer, this question (see comment for link), and this blog , I finally made my app to work behind SSL. 基于史蒂夫的答案,这个问题(请参阅注释以获取链接)以及该博客 ,我终于使我的应用程序在SSL后面运行。

I created an SSL certificate and key using the following command (unexperienced users like me shall note that these certificates are self-signed, therefore browsers classify the connection as insecure. However transactions are correctly encrypted. For more information on the command see the blog ): 我使用以下命令创建了SSL证书和密钥(像我这样的没有经验的用户会注意到,这些证书是自签名的,因此浏览器将连接分类为不安全。但是交易已正确加密。有关该命令的更多信息,请参阅Blog )。 :

dzdo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Changed my nginx.conf to (since I'm using DjangoWhiteNoise, my nginx conf doesn't handle static neither media files): 将我的nginx.conf更改为(因为我使用的是DjangoWhiteNoise,所以我的nginx conf不处理静态的两个媒体文件):

server {
    listen          80;
    server_name     HOSTNAME;
    rewrite ^/(.*)  https://HOST/$1 permanent;
}

server {
    listen 443 ssl;
    server_name     HOSTNAME;
    access_log      /var/log/nginx/HOSTNAME_access.log combined;
    error_log       /var/log/nginx/HOSTNAME_error.log error;

    # To create an SSL certificate:
    # dzdo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    location / {
        proxy_pass         http://unix:/tmp/HOST.socket;
        proxy_redirect     off;
        proxy_set_header   Host              $http_host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }

}

Finally, I set my Django security settings to: 最后,我将Django安全设置设置为:

...
SECURITY_MIDDLEWARE = ('django.middleware.security.SecurityMiddleware',)
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'SAMEORIGIN'
SECURE_HSTS_SECONDS = 60 
SECURE_BROWSER_XSS_FILTER = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')

Hope this can help folks like me. 希望这可以帮助像我这样的人。

Just in case, have you tried setting ALLOWED_HOSTS , too? 以防万一,您是否也尝试设置ALLOWED_HOSTS

Also, reading this from the docs : 另外, 从docs读取此内容:

If turning this to True causes infinite redirects, it probably means your site is running behind a proxy and can't tell which requests are secure and which are not. 如果将其设置为True会导致无限重定向,则可能意味着您的网站在代理后面运行,并且无法确定哪些请求是安全的,哪些不是安全的。 Your proxy likely sets a header to indicate secure requests; 您的代理可能会设置标头以指示安全请求; you can correct the problem by finding out what that header is and configuring the SECURE_PROXY_SSL_HEADER setting accordingly. 您可以通过找出该标头是什么并相应地配置SECURE_PROXY_SSL_HEADER设置来纠正问题。

then looking at what you have there in your nginx conf: 然后查看您的nginx conf中有什么:

listen 80
...
proxy_set_header X-Forwarded-Protocol $scheme;

Are you sure that $scheme is https and not http ? 您确定$schemehttps而不是http吗? You're listening on port 80, not port 443 and your SECURE_PROXY_SSL_HEADER setting looks like it's expecting https when it may be getting a unsecured http request forwarded. 您正在收听的80端口,没有端口443和您的SECURE_PROXY_SSL_HEADER设置看起来像它期待https时,它可能会得到转发的不安全的HTTP请求。

Just a guess, looking at the configs. 只是一个猜测,请看配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM