官方文档:https://fastapi.tiangolo.com/zh/deployment/versions/
关于 FastAPI 版本¶
FastAPI 已在许多应用程序和系统的生产环境中使用。 并且测试覆盖率保持在100%。 但其开发进度仍在快速推进。
经常添加新功能,定期修复错误,并且代码仍在持续改进。
这就是为什么当前版本仍然是0.x.x
,这反映出每个版本都可能有Breaking changes。 这遵循语义版本控制的约定。
你现在就可以使用 FastAPI 创建生产环境应用程序(你可能已经这样做了一段时间),你只需确保使用的版本可以与其余代码正确配合即可。
固定你的 fastapi
版本¶
你应该做的第一件事是将你正在使用的 FastAPI 版本“固定”到你知道适用于你的应用程序的特定最新版本。
例如,假设你在应用程序中使用版本0.45.0
。
如果你使用requirements.txt
文件,你可以使用以下命令指定版本:
fastapi==0.45.0
这意味着你将使用版本0.45.0
。
或者你也可以将其固定为:
fastapi>=0.45.0,<0.46.0
这意味着你将使用0.45.0
或更高版本,但低于0.46.0
,例如,版本0.45.2
仍会被接受。
如果你使用任何其他工具来管理你的安装,例如 Poetry、Pipenv 或其他工具,它们都有一种定义包的特定版本的方法。
可用版本¶
你可以在发行说明中查看可用版本(例如查看当前最新版本)。
关于版本¶
遵循语义版本控制约定,任何低于1.0.0
的版本都可能会添加 breaking changes。
FastAPI 还遵循这样的约定:任何PATCH
版本更改都是为了bug修复和non-breaking changes。
Tip
"PATCH"是最后一个数字,例如,在
0.2.3
中,PATCH版本是3
。
因此,你应该能够固定到如下版本:
fastapi>=0.45.0,<0.46.0
"MINOR"版本中会添加breaking changes和新功能。
Tip
"MINOR"是中间的数字,例如,在
0.2.3
中,MINOR版本是2
。
升级FastAPI版本¶
你应该为你的应用程序添加测试。
使用 FastAPI 编写测试非常简单(感谢 Starlette),请参考文档:测试
添加测试后,你可以将 FastAPI 版本升级到更新版本,并通过运行测试来确保所有代码都能正常工作。
如果一切正常,或者在进行必要的更改之后,并且所有测试都通过了,那么你可以将fastapi
固定到新的版本。
关于Starlette¶
你不应该固定starlette
的版本。
不同版本的 FastAPI 将使用特定的较新版本的 Starlette。
因此,FastAPI 自己可以使用正确的 Starlette 版本。
关于 Pydantic¶
Pydantic 包含针对 FastAPI 的测试及其自己的测试,因此 Pydantic 的新版本(1.0.0
以上)始终与 FastAPI 兼容。
你可以将 Pydantic 固定到适合你的1.0.0
以上和2.0.0
以下的任何版本。
例如:
pydantic>=1.2.0,<2.0.0
关于 HTTPS¶
人们很容易认为 HTTPS 仅仅是“启用”或“未启用”的东西。
但实际情况比这复杂得多。
提示
如果你很赶时间或不在乎,请继续阅读下一部分,下一部分会提供一个step-by-step的教程,告诉你怎么使用不同技术来把一切都配置好。
要从用户的视角了解 HTTPS 的基础知识,请查看 How HTTPS works - How HTTPS works。
现在,从开发人员的视角,在了解 HTTPS 时需要记住以下几点:
- 要使用 HTTPS,服务器需要拥有由第三方生成的"证书(certificate)"。
- 这些证书实际上是从第三方获取的,而不是“生成”的。
- 证书有生命周期。
- 它们会过期。
- 然后它们需要更新,再次从第三方获取。
- 连接的加密发生在 TCP 层。
- 这是 HTTP 协议下面的一层。
- 因此,证书和加密处理是在 HTTP之前完成的。
- TCP 不知道域名。 仅仅知道 IP 地址。
- 有关所请求的 特定域名 的信息位于 HTTP 数据中。
- HTTPS 证书“证明”某个域名,但协议和加密发生在 TCP 层,在知道正在处理哪个域名之前。
- 默认情况下,这意味着你每个 IP 地址只能拥有一个 HTTPS 证书。
- 无论你的服务器有多大,或者服务器上的每个应用程序有多小。
- 不过,对此有一个解决方案。
- TLS 协议(在 HTTP 之下的TCP 层处理加密的协议)有一个扩展,称为 SNI。
- SNI 扩展允许一台服务器(具有 单个 IP 地址)拥有 多个 HTTPS 证书 并提供 多个 HTTPS 域名/应用程序。
- 为此,服务器上会有单独的一个组件(程序)侦听公共 IP 地址,这个组件必须拥有服务器中的所有 HTTPS 证书。
- 获得安全连接后,通信协议仍然是HTTP。
- 内容是 加密过的,即使它们是通过 HTTP 协议 发送的。
通常的做法是在服务器上运行一个程序/HTTP 服务器并管理所有 HTTPS 部分:接收加密的 HTTPS 请求, 将 解密的 HTTP 请求 发送到在同一服务器中运行的实际 HTTP 应用程序(在本例中为 FastAPI 应用程序),从应用程序中获取 HTTP 响应, 使用适当的 HTTPS 证书对其进行加密并使用 HTTPS 将其发送回客户端。 此服务器通常被称为 TLS 终止代理(TLS Termination Proxy)。
你可以用作 TLS 终止代理的一些选项包括:
- Traefik(也可以处理证书更新)
- Caddy(也可以处理证书更新)
- Nginx
- HAProxy
Let's Encrypt¶
在 Let's Encrypt 之前,这些 HTTPS 证书 由受信任的第三方出售。
过去,获得这些证书的过程非常繁琐,需要大量的文书工作,而且证书非常昂贵。
但随后 Let's Encrypt 创建了。
它是 Linux 基金会的一个项目。 它以自动方式免费提供 HTTPS 证书。 这些证书可以使用所有符合标准的安全加密,并且有效期很短(大约 3 个月),因此安全性实际上更好,因为它们的生命周期缩短了。
域可以被安全地验证并自动生成证书。 这还允许自动更新这些证书。
我们的想法是自动获取和更新这些证书,以便你可以永远免费拥有安全的 HTTPS。
面向开发人员的 HTTPS¶
这里有一个 HTTPS API 看起来是什么样的示例,我们会分步说明,并且主要关注对开发人员重要的部分。
域名¶
第一步我们要先获取一些域名(Domain Name)。 然后可以在 DNS 服务器(可能是你的同一家云服务商提供的)中配置它。
你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个固定 公共IP地址。
在 DNS 服务器中,你可以配置一条记录(“A 记录”)以将 你的域名 指向你服务器的公共 IP 地址。
这个操作一般只需要在最开始执行一次。
Tip
域名这部分发生在 HTTPS 之前,由于这一切都依赖于域名和 IP 地址,所以先在这里提一下。
DNS¶
现在让我们关注真正的 HTTPS 部分。
首先,浏览器将通过 DNS 服务器 查询域名的IP 是什么,在本例中为 someapp.example.com
。
DNS 服务器会告诉浏览器使用某个特定的 IP 地址。 这将是你在 DNS 服务器中为你的服务器配置的公共 IP 地址。
TLS 握手开始¶
然后,浏览器将在端口 443(HTTPS 端口)上与该 IP 地址进行通信。
通信的第一部分只是建立客户端和服务器之间的连接并决定它们将使用的加密密钥等。
客户端和服务器之间建立 TLS 连接的过程称为 TLS 握手。
带有 SNI 扩展的 TLS¶
服务器中只有一个进程可以侦听特定 IP 地址的特定 端口。 可能有其他进程在同一 IP 地址的其他端口上侦听,但每个 IP 地址和端口组合只有一个进程。
TLS (HTTPS) 默认使用端口443
。 这就是我们需要的端口。
由于只有一个进程可以监听此端口,因此监听端口的进程将是 TLS 终止代理。
TLS 终止代理可以访问一个或多个 TLS 证书(HTTPS 证书)。
使用上面讨论的 SNI 扩展,TLS 终止代理将检查应该用于此连接的可用 TLS (HTTPS) 证书,并使用与客户端期望的域名相匹配的证书。
在这种情况下,它将使用someapp.example.com
的证书。
客户端已经信任生成该 TLS 证书的实体(在本例中为 Let's Encrypt,但我们稍后会看到),因此它可以验证该证书是否有效。
然后,通过使用证书,客户端和 TLS 终止代理 决定如何加密 TCP 通信 的其余部分。 这就完成了 TLS 握手 部分。
此后,客户端和服务器就拥有了加密的 TCP 连接,这就是 TLS 提供的功能。 然后他们可以使用该连接来启动实际的 HTTP 通信。
这就是 HTTPS,它只是 安全 TLS 连接 内的普通 HTTP,而不是纯粹的(未加密的)TCP 连接。
Tip
请注意,通信加密发生在 TCP 层,而不是 HTTP 层。
HTTPS 请求¶
现在客户端和服务器(特别是浏览器和 TLS 终止代理)具有 加密的 TCP 连接,它们可以开始 HTTP 通信。
接下来,客户端发送一个 HTTPS 请求。 这其实只是一个通过 TLS 加密连接的 HTTP 请求。
解密请求¶
TLS 终止代理将使用协商好的加密算法解密请求,并将(解密的)HTTP 请求传输到运行应用程序的进程(例如运行 FastAPI 应用的 Uvicorn 进程)。
HTTP 响应¶
应用程序将处理请求并向 TLS 终止代理发送(未加密)HTTP 响应。
HTTPS 响应¶
然后,TLS 终止代理将使用之前协商的加密算法(以someapp.example.com
的证书开头)对响应进行加密,并将其发送回浏览器。
接下来,浏览器将验证响应是否有效和是否使用了正确的加密密钥等。然后它会解密响应并处理它。
客户端(浏览器)将知道响应来自正确的服务器,因为它使用了他们之前使用 HTTPS 证书 协商出的加密算法。
多个应用程序¶
在同一台(或多台)服务器中,可能存在多个应用程序,例如其他 API 程序或数据库。
只有一个进程可以处理特定的 IP 和端口(在我们的示例中为 TLS 终止代理),但其他应用程序/进程也可以在服务器上运行,只要它们不尝试使用相同的 公共 IP 和端口的组合。
这样,TLS 终止代理就可以为多个应用程序处理多个域名的 HTTPS 和证书,然后在每种情况下将请求传输到正确的应用程序。
证书更新¶
在未来的某个时候,每个证书都会过期(大约在获得证书后 3 个月)。
然后,会有另一个程序(在某些情况下是另一个程序,在某些情况下可能是同一个 TLS 终止代理)与 Let's Encrypt 通信并更新证书。
TLS 证书 与域名相关联,而不是与 IP 地址相关联。
因此,要更新证书,更新程序需要向权威机构(Let's Encrypt)证明它确实“拥有”并控制该域名。
有多种方法可以做到这一点。 一些流行的方式是:
- 修改一些DNS记录。
- 为此,续订程序需要支持 DNS 提供商的 API,因此,要看你使用的 DNS 提供商是否提供这一功能。
- 在与域名关联的公共 IP 地址上作为服务器运行(至少在证书获取过程中)。
- 正如我们上面所说,只有一个进程可以监听特定的 IP 和端口。
- 这就是当同一个 TLS 终止代理还负责证书续订过程时它非常有用的原因之一。
- 否则,你可能需要暂时停止 TLS 终止代理,启动续订程序以获取证书,然后使用 TLS 终止代理配置它们,然后重新启动 TLS 终止代理。 这并不理想,因为你的应用程序在 TLS 终止代理关闭期间将不可用。
通过拥有一个单独的系统来使用 TLS 终止代理来处理 HTTPS, 而不是直接将 TLS 证书与应用程序服务器一起使用 (例如 Uvicorn),你可以在 更新证书的过程中同时保持提供服务。
回顾¶
拥有HTTPS 非常重要,并且在大多数情况下相当关键。 作为开发人员,你围绕 HTTPS 所做的大部分努力就是理解这些概念以及它们的工作原理。
一旦你了解了面向开发人员的 HTTPS 的基础知识,你就可以轻松组合和配置不同的工具,以帮助你以简单的方式管理一切。
在接下来的一些章节中,我将向你展示几个为 FastAPI 应用程序设置 HTTPS 的具体示例。 🔒
申请Cerbot的HTTPS服务
网站:Certbot
a project of the Electronic Frontier Foundation 。采用的是Automatic Certificate Management Environment (ACME):RFC 8555 - Automatic Certificate Management Environment (ACME)
Certbot 是一个用于自动获取和管理 Let's Encrypt 提供的免费 SSL/TLS 证书的工具。要使用 Certbot 获取有效的 HTTPS 证书,通常需要具备以下条件:
- 有效的域名:Let's Encrypt 需要验证您对域名的所有权,以确保证书仅颁发给合法的域名拥有者。
- 可访问的服务器:需要确保域名指向的服务器能够通过互联网访问,以便完成域名验证过程。
一如既往,个人习惯使用nginx作为后端,因此在Cerbot网站,选择Website为Nginx ,操作系统可以根据自己的实际情况选择,比如Ubuntu Linux和FreeBSD。
Ubuntu Linux下申请步骤
Certbot Instructions | Certbot
- SSH into the server
SSH into the server running your HTTP website as a user with sudo privileges.
- Install system dependencies
System dependencies may include Python 3.6+ including the venv module and Augeas for the Apache plugin.
If you're having trouble installing cryptography, you may need to install additional dependencies. See the cryptography project's site for more information.
Commands to install system dependencies may look like the following, run on the commandline on the machine.
For APT-based distributions (e.g. Debian, Ubuntu ...):
- sudo apt update
- sudo apt install python3 python3-venv libaugeas0
For RPM-based distributions (e.g. Fedora, CentOS ...):
sudo dnf install python3 augeas-libs
Note that old distributions use
yum
instead ofdnf
, and that RHEL-based distributions usepython3X
instead ofpython3
(e.g.python36<
).These packages may have slightly different names on other distributions; a search such as "augeas on " will probably yield helpful results.
- Remove certbot-auto and any Certbot OS packages
If you have any Certbot packages installed using an OS package manager like
apt
,dnf
, oryum
, you should remove them before installing the Certbot snap to ensure that when you run the commandcertbot
the snap is used rather than the installation from your OS package manager. The exact command to do this depends on your OS, but common examples aresudo apt-get remove certbot
,sudo dnf remove certbot
, orsudo yum remove certbot
. - Set up a Python virtual environment
Execute the following instructions on the command line on the machine to set up a virtual environment.
- sudo python3 -m venv /opt/certbot/
- sudo /opt/certbot/bin/pip install --upgrade pip
- Install Certbot
Run this command on the command line on the machine to install Certbot.
sudo /opt/certbot/bin/pip install certbot certbot-nginx
- Prepare the Certbot command
Execute the following instruction on the command line on the machine to ensure that the
certbot
command can be run.sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
- Choose how you'd like to run Certbot
Either get and install your certificates...
Run this command to get a certificate and have Certbot edit your nginx configuration automatically to serve it, turning on HTTPS access in a single step.
sudo certbot --nginx
Or, just get a certificate
If you're feeling more conservative and would like to make the changes to your nginx configuration by hand, run this command.
sudo certbot certonly --nginx
- Set up automatic renewal
We recommend running the following line, which will add a cron job to the default crontab.
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
- Confirm that Certbot worked
To confirm that your site is set up properly, visit
https://yourwebsite.com/
in your browser and look for the lock icon in the URL bar. - [Monthly] Upgrade certbot
It's important to occasionally update Certbot to keep it up-to-date. To do this, run the following command on the command line on the machine.
sudo /opt/certbot/bin/pip install --upgrade certbot certbot-nginx
If this step leads to errors, run
sudo rm -rf /opt/certbot
and repeat all installation instructions.
FreeBSD nginx下申请步骤
Certbot Instructions | Certbot
- SSH into the server
SSH into the server running your HTTP website as a user with sudo privileges.
- Install Certbot
Either install the Certbot package...
Run this command on the command line on the machine to install the Certbot package.
pkg install security/py-certbot-nginx
Or, if you prefer, install Certbot from ports
Run this command on the command line on the machine to install Certbot from ports.
cd /usr/ports/security/py-certbot-nginx && make install clean
- Choose how you'd like to run Certbot
Either get and install your certificates...
Run this command to get a certificate and have Certbot edit your nginx configuration automatically to serve it, turning on HTTPS access in a single step.
sudo certbot --nginx
Or, just get a certificate
If you're feeling more conservative and would like to make the changes to your nginx configuration by hand, run this command.
sudo certbot certonly --nginx
- Test automatic renewal
The Certbot packages on your system come with a cron job or systemd timer that will renew your certificates automatically before they expire. You will not need to run Certbot again, unless you change your configuration. You can test automatic renewal for your certificates by running this command:
sudo certbot renew --dry-run
The command to renew certbot is installed in one of the following locations:
/etc/crontab/
/etc/cron.*/*
systemctl list-timers
- Confirm that Certbot worked
To confirm that your site is set up properly, visit
https://yourwebsite.com/
in your browser and look for the lock icon in the URL bar.
实践
这次我们来进行申请https证书的实践。操作系统为Ubuntu22.04, web软件为nginx。 nginx尽管比uvicorn和Gunicorn要复杂一点点,但是它功能强大,它在性能优化、资源管理、安全性和可扩展性等方面带来了显著的优势,使得整个系统更加健壮和高效。因此,尤其在生产环境中,结合使用 nginx 和 uvicorn/Gunicorn 是一种常见且推荐的部署方式。
安装https证书相关软件
登录自己的服务器,执行命令安装相关软件:
首先创建python虚拟环境
安装python3软件
sudo apt update
sudo apt install python3 python3-venv libaugeas0
创建python虚拟环境
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
如果已经有了python的环境,那么apt install python3 python3-venv以及后面的创建虚拟环境都可以忽略 。
删除系统自带的certbot包
sudo apt-get remove certbot
安装python环境里的certbot包
sudo /opt/certbot/bin/pip install certbot certbot-nginx
当然对于有自己python环境的情况,命令可以简化成:
pip install certbot certbot-nginx
将Certbot命令建立链接,链到/usr/bin目录
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
如果是自定义的python虚拟环境,则cerbot的路径要做相应的改变,比如:
sudo ln -s /mnt/data/work/py39/bin/certbot /usr/bin/certbot
申请certbot https证书
开始申请证书,可以申请后自动进行nginx的配置:
sudo certbot --nginx
也可以只申请证书,再去手工配置nginx里的证书:
sudo certbot certonly --nginx
因为cerbot已经ln链接到/usr/bin目录,所以cerbot指令是可以直接执行而不必输入路径。
我这里使用了只申请证书,手工配置nginx的方式:
sudo certbot certonly --nginx
执行后会询问email地址,
按照提示输入email地址,然后询问哪些域名申请https,建议所有。
直接回车就是所有域名
然后提示申请完毕
Requesting a certificate for quye.com and 4 more domains
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/quye.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/quye.com/privkey.pem
This certificate expires on 2025-02-10.
These files will be updated when the certificate renews.
NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
按照提示,去学习怎么设置自动续约,执行这条命令
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}'); echo "0 0,12 * * * root sleep $SLEEPTIME && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
这条命令的实际效果是:每天的 00:00 和 12:00,系统将随机等待一段时间(最多 1 小时),然后在后台静默地尝试续订 Let's Encrypt 证书。
文件修改的是/etc/crontab文件:
0 0,12 * * * root sleep 2483 && certbot renew -q
原来每天一次续订还是太频繁了,可以修改成每月一次,可以手工vi修改crontab文件:
sudo vi /etc/crontab
0 0,12 1 * * root sleep 2483 && certbot renew -q
也可以执行下面命令:
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}'); echo "0 0,12 1 * * root sleep $SLEEPTIME && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
确认服务
Confirm that Certbot worked
To confirm that your site is set up properly, visit https://yourwebsite.com/
in your browser and look for the lock icon in the URL bar.
配置nginx
在/etc/nginx/的配置文件quye.conf中添加一段配置
server {
listen 443 ssl;
server_name quye.com www.quye.com;
ssl_certificate //letsencrypt/live/quye.com/fullchain.pem;
ssl_certificate_key /etc//live/quye.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /mnt/quye;
index index.html index.htm;
}
# 其他配置...
}
重启nginx
sudo service nginx restart
登录网站检验https
好了,现在使用登录网站:济宁市极快软件科技有限公司
可以看到现在的网站就有了https啦! 可以在浏览器查看网站证书,现在咱也是有证的人啦!
实践完成,收工!