简介

最近在用 FastAPI 和 Vue 开发项目时,发现 FastAPI 默认使用 http 协议。这导致在访问网站时会出现"不安全"警告,严重影响用户体验。因此,决定将项目升级到 https。

为什么需要 https?

主要是从安全性以及用户体验考虑,

安全性上:

  • http 通过 SSL/TLS 协议对数据进行加密,防止数据在传输过程中被窃听或篡改;

  • 可以保护用户敏感信息(如密码、个人信息等)的安全;

  • 确保网站内容的完整性,防止中间人攻击。

用户体验上:

  • 浏览器对 http 网站会显示"不安全"警告;

  • 部分浏览器功能(如地理位置、摄像头等)要求必须使用 https;

  • 有利于搜索引擎优化(SEO),Google 会优先考虑 https 网站。

接下来是我记录的这次替换过程。

1 前端

首先是 web 和前端部分,之前在部署过程中用的是 nginx ,主要是可以通过宝塔面板进行可视化操作;但是在替换 https 的过程中换成了更加轻量,简单的 caddy。

1.1 为什么选择 Caddy?

相比传统的 Nginx,Caddy 有以下优势:

自动 https:

  • 自动申请和续期 Let's Encrypt 证书

  • 零配置 https 支持,大大简化了配置过程

简单易用:

  • 配置文件语法简洁明了

  • 默认配置已经很安全,无需额外的安全配置

  • 内置了现代 Web 特性支持

轻量:

  • 资源占用少

  • 启动快速

  • 依赖少,易于部署

1.2 安装 caddy

caddy官方文档:Welcome — Caddy Documentation

ubuntu:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

其他操作系统参考官方文档。

安装完成后要修改 caddy 的配置文件,/etc/caddy/Caddyfile

以下是一个简单的配置文件:

example.com {
    # 根目录设置
    root * /var/www/example.com
​
    # 启用文件服务器
    file_server
​
    # 启用单页应用支持
    try_files {path} /index.html
​
    # 启用压缩
    encode gzip
​
    # 基本安全头
    header {
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
    }
}

重新启动

sudo systemctl restart caddy

前端部分只需要将原本发送 http 请求部分改为 https 即可,然后将 build 后的文件放在对应目录下即可。

1.3 证书

由于 caddy 会自动部署证书,所以这一步可以忽略。

2 后端

2.1 获取证书

FastAPI 要支持 https,需要配置 SSL 证书。我们可以通过 Python 生成一个自签名证书用于开发和测试。

注意:自签名证书仅建议用于开发环境。在生产环境中,应使用受信任的证书颁发机构(CA)签发的证书。比如可以使用 cloudflare 的证书。

首先安装依赖:

pip install pyOpenSSL

然后创建并执行以下文件:

from OpenSSL import crypto, SSL
​
​
def generate_certificate(
        organization="PrivacyFilter",
        common_name="<你的ipv4地址>:8000",
        country="NL",
        duration=(365 * 24 * 60 * 60),
        keyfilename="key.pem",
        certfilename="cert.pem"):
    k = crypto.PKey()
    k.generate_key(crypto.TYPE_RSA, 4096)
​
    cert = crypto.X509()
    cert.get_subject().C = country
    cert.get_subject().O = organization
    cert.get_subject().CN = common_name
    cert.gmtime_adj_notBefore(0)
    cert.gmtime_adj_notAfter(duration)
    cert.set_issuer(cert.get_subject())
    cert.set_pubkey(k)
    cert.sign(k, 'sha512')
​
    with open(keyfilename, "wt") as keyfile:
        keyfile.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"))
    with open(certfilename, "wt") as certfile:
        certfile.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
​
​
if __name__ == '__main__':
    generate_certificate()
​
​

成功执行后会生成

  • cert.pem (证书文件)

  • key.pem (私钥文件)

2.2 FastAPI 配置

在 FastAPI 应用中启用 https ,只需在启动时配置 SSL 证书:

import uvicorn
from fastapi import FastAPI
​
app = FastAPI()
​
if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8000,
        ssl_keyfile="./key.pem",
        ssl_certfile="./cert.pem"
    )

2.3 方法二

上面这种方式还是向 ipv4 地址发送请求,所以只能使用自签证书。

我们也可以选择添加一个子域名解析到后端服务器,如果前后端是同一台服务器可以用 caddy 设置一个反向代理。

前面说到 caddy 可以自动部署证书,这样前端就可以向子域名发送 https 请求,同样实现了后端的升级。

3 其他

略微补充下 cloudflare 的证书获取以及如何使用宝塔面板中的 nginx 简单部署。

3.1 cloudfare 证书获取

3.1.1 cloudflare 简介

简单点说,Cloudflare 是一家提供 CDN、安全防护、DNS 解析等服务的全球性云服务提供商,通过其全球网络帮助网站提升访问速度、增强安全性和改善可靠性。

https://www.cloudflare.com/zh-cn/learning/what-is-cloudflare/

3.1.2 获取

找到管理的域名中的 SSL/TLS ,点击 Origin Server,右侧有一个Create Certificate

点击后填写你想获取证书的域名。

注意:例如你的域名是example.com那么你只需要填写example.com即可,一定不要添加*.example.com,否则会让所有子域名都重定向到主域名。

点击Create后保存即可。

3.2 宝塔面板部署 SSL 证书

部署好站点之后找到 SSL ,分别将证书和私钥复制过来,点击启用并且强制 https 就好了。