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 # 防止浏览器猜测资产的内容类型
还有一种方法,但是我没有尝试
Django
的SECURE_SSL_REDIRECT = True
也可实现 80 端口的http
请求永久地重定向至https
, 与Nginx
的 301 重定向设置选其一即可。Django
以上的几个安全设置均依赖下面这个SecurityMiddleware
中间件。
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
]
这时候如果在模板中使用即可自动识别
https