Django 从 0 到 1 打造完整电商平台:HTTPS 配置与域名绑定

18 阅读7分钟

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在公众号、今日头条持续发布最新文章,助你少走弯路。


上一篇我们用 Docker 把整个电商平台容器化了,几条命令就能在任何服务器上跑起来。但还有一个问题:用户浏览器地址栏里显示的仍然是 http://,访问时会有“不安全”的提示。对于处理用户支付、账号密码的电商网站来说,这绝对不行。

今天我们就来完成上线前的最后一步——配置 HTTPS 加密访问,并绑定自己的域名。我会带你从域名解析开始,到申请免费的 SSL 证书,再到 Nginx 配置自动续期,让用户通过 https://www.你的域名.com 安全地浏览和下单,彻底达到生产标准。


一、为什么一定要 HTTPS?

HTTP 协议是明文传输的,请求和响应在网络上“裸奔”。任何人都可以在路由器、网关等节点截获数据,看到用户的密码、订单详情,甚至注入广告或恶意代码。

HTTPS 通过在 HTTP 和 TCP 之间加上 TLS/SSL 加密层,实现了三重保护:

  1. 加密通信:数据在传输过程中被加密,无法被窃听。

  2. 身份认证:证书由受信任的 CA(证书颁发机构)签发,确保你访问的是真实的网站,而非假冒网站。

  3. 数据完整性:防止数据在传输过程中被篡改。

电商网站处理用户登录、支付,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 和支付回调地址

.envsettings_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.comnotify_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,查看 sessionidcsrftoken,它们的 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 篇。