Django教程: 支持HTTPS访问及Nginx配置SSL证书



title: Django教程: 支持HTTPS访问及Nginx配置SSL证书
author: hongwei
top: false
cover: false
coverImg: /medias/featureimages/13.jpg
toc: true
mathjax: false
summary: Django支持HTTPS访问及Nginx配置SSL证书
categories:

  • Django
    tags:
  • python
  • django
  • nginx

urlname: django-nginx-https-ssl
date: 2020-11-02 23:33:46
img:
password:
updated:


什么是 HTTPS?

简单来说:HTTPS = HTTP + SSL / TLS

也就是在 HTTP(超文本传输协议)上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过 TLS 进行加密,所以传输的数据都是加密后的数据。

HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),即安全套接字层超文本传输协议,它是以安全为目标的 HTTP 通道,在 HTTP 的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS 在 HTTP 的基础下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP 与 TCP 之间)。

注意:HTTP协议默认使用的是 80 端口,而HTTPS协议默认使用的是 443 端口。

获取 SSL 证书

SSL 证书,通常包括一张证书(.cert 或.pem)和一个私有密钥文件(.key)。

SSL 证书分很多类型,贵的都是高级别的 HTTPS 证书,比如 EV 证书。免费的 HTTPS 证书是低级别的证书,如 DV 证书,DV 证书只验证域名所有权,且功能有限制,支持单个或者少数几个域名,所以免费。个人站长可以申请免费 SSL 证书来用,成本低,也能起到加密作用。

其实免费的 SSL 证书阿里云、腾讯云、Lets Encrypt、freessl 等等都有,足够个人网站使用。以阿里云举例


购买证书

配置 nginx

将获取到的证书和密钥上传到服务器的任何一个指定目录,如我的在下面是基本配置

server {
    listen 443 ssl;  # 端口
    server_name blog.zhwei.cn;  # 域名
    ssl_certificate   /etc/nginx/cert/fullchain.crt;  # 证书
    ssl_certificate_key  /etc/nginx/cert/privkey.key;  # 密钥
}

Django部署时以Nginx做反向代理和静态文件服务器,这里以基于 Docker 的 Django 容器化部署教程为例进行配置

nginx 配置

server {
    listen 443 ssl;
    server_name blog.zhwei.cn;  # 域名

    ssl on;
    ssl_certificate   /etc/nginx/cert/fullchain.crt;
    ssl_certificate_key  /etc/nginx/cert/privkey.key;
    ssl_ciphers                 TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers    on;
    ssl_protocols                TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_session_cache            shared:SSL:50m;
    ssl_session_timeout          1d;
    ssl_session_tickets          on;

    # 配置docker-compose.yml中挂载的 static
    location /static/ {
        autoindex on;
        alias /opt/hw-blog/static/;
    }

    # 配置docker-compose.yml中挂载的 media
    location /media/ {
        autoindex on;
        alias /opt/hw-blog/media/;

    }

    # 拦截所有请求 服务转发 端口需要一致
    location / {
        proxy_pass http://website:7000;
        proxy_set_header Host $http_host; #header添加请求host信息
        proxy_set_header X-Forwarded-Proto $scheme
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 增加代理记录
    }
}

如果想http请求永久地重定向至https只需加上下面的内容

server {
    listen       80;
    server_name  blog.zhwei.cn; # 域名
    return 301 https://$host$request_uri;
}

docker-compose.yml需要把证书目录映射

 nginx:
    image: nginx:latest
    container_name: hw_nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./django/static:/opt/hw-blog/static
      - ./django/media:/opt/hw-blog/media
      - ./nginx:/etc/nginx/conf.d
      - /opt/ssl/blog.zhwei.cn:/etc/nginx/cert  # 证书目录
    depends_on:
      - website
    networks:
      - django_network

配置 Django 支持 https

Django网站和用户数据提供更高级别的保护,需要在settings.py新增如下安全配置

# SECURITY安全设置 - 支持http时建议开启
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")   # 推荐
SECURE_SSL_REDIRECT = True # 将所有非SSL请求永久重定向到SSL
SESSION_COOKIE_SECURE = True # 仅通过https传输cookie
CSRF_COOKIE_SECURE = True # 仅通过https传输cookie
SECURE_HSTS_INCLUDE_SUBDOMAINS = True # 严格要求使用https协议传输
SECURE_HSTS_PRELOAD = True # HSTS为
SECURE_HSTS_SECONDS = 60
SECURE_CONTENT_TYPE_NOSNIFF = True # 防止浏览器猜测资产的内容类型

还有一种方法,但是我没有尝试

DjangoSECURE_SSL_REDIRECT = True也可实现 80 端口的http请求永久地重定向至https, 与Nginx的 301 重定向设置选其一即可。Django以上的几个安全设置均依赖下面这个SecurityMiddleware中间件。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
]

这时候如果在模板中使用即可自动识别https


文章作者:   HONGWEI
版权声明:   本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 HONGWEI !
评论
  目录