IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在公众号、今日头条持续发布最新文章,助你少走弯路。
上一篇我们用 Docker 把整个电商平台容器化了,几条命令就能在任何服务器上跑起来。但还有一个问题:用户浏览器地址栏里显示的仍然是 http://,访问时会有“不安全”的提示。对于处理用户支付、账号密码的电商网站来说,这绝对不行。
今天我们就来完成上线前的最后一步——配置 HTTPS 加密访问,并绑定自己的域名。我会带你从域名解析开始,到申请免费的 SSL 证书,再到 Nginx 配置自动续期,让用户通过 https://www.你的域名.com 安全地浏览和下单,彻底达到生产标准。
一、为什么一定要 HTTPS?
HTTP 协议是明文传输的,请求和响应在网络上“裸奔”。任何人都可以在路由器、网关等节点截获数据,看到用户的密码、订单详情,甚至注入广告或恶意代码。
HTTPS 通过在 HTTP 和 TCP 之间加上 TLS/SSL 加密层,实现了三重保护:
-
加密通信:数据在传输过程中被加密,无法被窃听。
-
身份认证:证书由受信任的 CA(证书颁发机构)签发,确保你访问的是真实的网站,而非假冒网站。
-
数据完整性:防止数据在传输过程中被篡改。
电商网站处理用户登录、支付,HTTPS 是强制性要求。支付宝的支付回调也强制要求 HTTPS。
二、域名准备与解析
2.1 购买域名
在阿里云(万网)、腾讯云 DNSPod、GoDaddy 等平台购买一个域名。假设我们买的域名是 myecommercestore.com。
2.2 DNS 解析
登录域名管理控制台,添加两条 A 记录,将域名指向你的服务器公网 IP:
-
@代表myecommercestore.com(裸域名) -
www代表www.myecommercestore.com
保存后,等待 DNS 解析生效(通常几分钟到几小时,可以通过 ping 你的域名 检查是否已解析到服务器 IP)。
ping myecommercestore.com
控制台输出:
PING myecommercestore.com (123.456.789.0): 56 data bytes
64 bytes from 123.456.789.0: icmp_seq=0 ttl=64 time=1.234 ms
如果显示你服务器的 IP,说明解析已生效。
三、使用 Let's Encrypt 获取免费 SSL 证书
Let's Encrypt 是免费的、自动化的证书颁发机构,被全球广泛信任。其客户端工具 certbot 可以自动获取和续期证书。
3.1 Nginx 直接部署方案(第 27 篇方式)
如果你使用第 27 篇的 Nginx + uWSGI 直接部署方式(非 Docker),按以下步骤操作。
安装 Certbot 和 Nginx 插件:
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
获取证书并自动修改 Nginx 配置:
sudo certbot --nginx -d myecommercestore.com -d www.myecommercestore.com
按提示输入邮箱(用于证书到期提醒),同意服务条款。
控制台输出:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for myecommercestore.com
http-01 challenge for www.myecommercestore.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/django_ecommerce
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/django_ecommerce
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled HTTPS on
https://myecommercestore.com and https://www.myecommercestore.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certbot 自动修改了 Nginx 配置,将所有 HTTP 请求重定向到 HTTPS,并添加了 SSL 证书配置。
检查自动续期:
Let's Encrypt 证书有效期 90 天,Certbot 安装时会自动添加一个 systemd timer 定期续期。
sudo certbot renew --dry-run
如果无错误,表示自动续期已正常工作。
3.2 Docker Compose 部署方案(第 28 篇方式)
如果使用 Docker,我们可以在 docker-compose 中增加一个 certbot 服务来获取证书,并在 Nginx 容器中挂载证书。
步骤一:创建 certbot 目录和配置
在项目根目录创建 certbot/ 目录用于存放证书和验证文件。
mkdir -p certbot/conf certbot/www
步骤二:修改 docker-compose.yml
在 services 中增加 certbot 服务,并修改 Nginx 配置,添加证书挂载。
services:
# ... 其他服务保持不变 ...
nginx:
image: nginx:1.25
container_name: ecom_nginx
ports:
- "80:80"
- "443:443" # 开放 443 端口
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- static_volume:/app/staticfiles
- media_volume:/app/media
- ./certbot/conf:/etc/letsencrypt # 证书目录
- ./certbot/www:/var/www/certbot # ACME 验证目录
depends_on:
- web
restart: unless-stopped
certbot:
image: certbot/certbot
container_name: ecom_certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
步骤三:修改 Nginx 配置
更新 nginx/nginx.conf,添加 HTTPS server 块,并增加 .well-known/acme-challenge 路径用于证书验证:
# HTTP server(用于证书验证和强制跳转 HTTPS)
server {
listen 80;
server_name myecommercestore.com www.myecommercestore.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl;
server_name myecommercestore.com www.myecommercestore.com;
ssl_certificate /etc/letsencrypt/live/myecommercestore.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myecommercestore.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /static/ {
alias /app/staticfiles/;
expires 30d;
}
location /media/ {
alias /app/media/;
expires 7d;
}
location / {
proxy_pass http://web:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
client_max_body_size 10M;
}
步骤四:首次获取证书
先启动 Nginx(不带 SSL 配置,因为我们还没有证书文件,可以先注释掉 443 部分,只保留 80 和验证路径,待证书获取后再启用完整配置)。
更简单的做法:使用一个临时的初始化脚本来获取证书。
创建一个 init-letsencrypt.sh:
#!/bin/bash
domains=(myecommercestore.com www.myecommercestore.com)
email="admin@myecommercestore.com" # 你的邮箱
staging=0 # 设为 1 测试,0 获取真实证书
docker-compose run --rm certbot certonly --webroot -w /var/www/certbot \
--email $email \
--domains "${domains[*]}" \
--agree-tos \
--no-eff-email \
$([ $staging = "1" ] && echo "--staging") \
--force-renewal
执行脚本:
chmod +x init-letsencrypt.sh
./init-letsencrypt.sh
控制台输出:
Requesting a certificate for myecommercestore.com and www.myecommercestore.com
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/myecommercestore.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/myecommercestore.com/privkey.pem
证书获取成功后,修改 Nginx 配置启用 HTTPS,然后重启 Nginx:
docker-compose restart nginx
四、Django 安全配置
部署 HTTPS 后,还需要在 Django 的 settings 中做一些安全设置。
编辑 django_ecommerce/settings_production.py:
# HTTPS 安全设置
SECURE_SSL_REDIRECT = True # 将所有 HTTP 请求重定向到 HTTPS
SECURE_HSTS_SECONDS = 31536000 # 强制浏览器在一年内使用 HTTPS 访问
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_BROWSER_XSS_FILTER = True # XSS 保护
SECURE_CONTENT_TYPE_NOSNIFF = True # 防止 MIME 类型嗅探
CSRF_COOKIE_SECURE = True # CSRF Cookie 仅在 HTTPS 下传输
SESSION_COOKIE_SECURE = True # Session Cookie 仅在 HTTPS 下传输
# 反向代理后的安全设置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
注意:SECURE_SSL_REDIRECT 在 Nginx 已经处理重定向时,可以关闭(设为 False),否则可能导致重定向循环。通常让 Nginx 处理 80→443 重定向,Django 设置 SECURE_PROXY_SSL_HEADER 即可识别请求是否为 HTTPS。
五、更新 ALLOWED_HOSTS 和支付回调地址
在 .env 或 settings_production.py 中,更新允许的主机和支付宝回调 URL:
ALLOWED_HOSTS = ['myecommercestore.com', 'www.myecommercestore.com', 'localhost', '127.0.0.1']
ALIPAY_RETURN_URL = 'https://www.myecommercestore.com/payment/return/'
ALIPAY_NOTIFY_URL = 'https://www.myecommercestore.com/payment/notify/'
如果使用支付宝沙箱,注意沙箱的网关是 https://openapi-sandbox.dl.alipaydev.com,notify_url 必须使用 https://,否则支付宝会拒绝发送通知。
六、测试 HTTPS 部署
6.1 访问验证
在浏览器输入 https://www.myecommercestore.com,你应该看到:
-
地址栏左侧出现锁形图标,显示“连接是安全的”。
-
网站功能完全正常(注册、登录、浏览、下单)。
-
HTTP 地址自动跳转到 HTTPS。
6.2 SSL 评级测试
使用 SSL Labs 测试你的域名安全性:
访问 www.ssllabs.com/ssltest/,输入你的域名。
通常 Let's Encrypt + 现代 Nginx 配置可达到 A 或 A+ 评级。
6.3 强制 HTTPS 测试
直接访问 http://myecommercestore.com,应被重定向到 https://myecommercestore.com。
使用 curl 验证:
curl -I http://myecommercestore.com
控制台输出:
HTTP/1.1 301 Moved Permanently
Server: nginx/1.25.0
Location: https://myecommercestore.com/
6.4 Django 安全设置验证
登录后,打开浏览器开发者工具 → Application → Cookies,查看 sessionid 和 csrftoken,它们的 Secure 属性应被勾选,表示仅在 HTTPS 下传输。
七、常见问题与排查
八、总结与下集预告
今天我们完成了电商平台的“上线最后一公里”——HTTPS 配置与域名绑定:
-
购买了域名并完成 DNS 解析;
-
使用 Let's Encrypt 获取了免费的 SSL 证书;
-
针对直装和 Docker 两种方式分别配置了 HTTPS;
-
更新了 Django 的安全设置,确保 Cookie 安全;
-
测试了强制 HTTPS 跳转和 SSL 评级。
现在,你的电商平台已经达到了商用的安全标准,可以通过 https://www.你的域名.com 正大光明地接客了!
整个系列也进入了最后的收尾阶段。第 30 篇,我将带大家回顾这 30 篇的完整项目成果,展示系统功能全景,并给出后续扩展方向——微服务化、Kubernetes 部署、国际化、移动端 API、AI 推荐等,为你的技术进阶指明道路。
想了解更多还可以去公众号、今日头条搜索「IT策士」,一起升级 IT 思维 !
本文为《Django 从 0 到 1 打造完整电商平台》系列第 29 篇。