Files
fastapi/docs/zh/docs/tutorial/security/first-steps.md
Sebastián Ramírez 376e108580 🌐 Update translations for zh (update-outdated) (#14843)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Yurii Motov <yurii.motov.monte@gmail.com>
2026-02-08 11:39:41 +01:00

7.6 KiB
Raw Blame History

安全 - 第一步

假设你的后端 API 位于某个域名下。

前端在另一个域名,或同一域名的不同路径(或在移动应用中)。

你希望前端能通过usernamepassword 与后端进行身份验证。

我们可以用 OAuth2FastAPI 中实现它。

但为了节省你的时间,不必为获取少量信息而通读冗长的规范。

我们直接使用 FastAPI 提供的安全工具。

效果预览

先直接运行代码看看效果,之后再回过头理解其背后的原理。

创建 main.py

把下面的示例代码复制到 main.py

{* ../../docs_src/security/tutorial001_an_py39.py *}

运行

/// info | 信息

当你使用命令 pip install "fastapi[standard]" 安装 FastAPI 时,python-multipart 包会自动安装。

但是,如果你使用 pip install fastapi,默认不会包含 python-multipart 包。

如需手动安装,请先创建并激活虚拟环境{.internal-link target=_blank},然后执行:

$ pip install python-multipart

这是因为 OAuth2 使用“表单数据”来发送 usernamepassword

///

用下面的命令运行示例:

$ fastapi dev main.py

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

查看

打开交互式文档:http://127.0.0.1:8000/docs

你会看到类似这样的界面:

/// check | Authorize 按钮!

页面右上角已经有一个崭新的“Authorize”按钮。

你的路径操作右上角还有一个可点击的小锁图标。

///

点击它,会弹出一个授权表单,可输入 usernamepassword(以及其它可选字段):

/// note | 注意

目前无论在表单中输入什么都不会生效,我们稍后就会实现它。

///

这当然不是面向最终用户的前端,但它是一个很棒的自动化工具,可交互式地为整个 API 提供文档。

前端团队(也可能就是你自己)可以使用它。

第三方应用和系统也可以使用它。

你也可以用它来调试、检查和测试同一个应用。

password

现在回过头来理解这些内容。

password “流”flow是 OAuth2 定义的处理安全与身份验证的一种方式。

OAuth2 的设计目标是让后端或 API 与负责用户认证的服务器解耦。

但在这个例子中,FastAPI 应用同时处理 API 和认证。

从这个简化的角度来看看流程:

  • 用户在前端输入 usernamepassword,然后按下 Enter
  • 前端(运行在用户浏览器中)把 usernamepassword 发送到我们 API 中的特定 URL使用 tokenUrl="token" 声明)。
  • API 校验 usernamepassword,并返回一个“令牌”(这些我们尚未实现)。
    • “令牌”只是一个字符串,包含一些内容,之后可用来验证该用户。
    • 通常,令牌会在一段时间后过期。
      • 因此,用户过一段时间需要重新登录。
      • 如果令牌被窃取,风险也更小。它不像一把永久有效的钥匙(在大多数情况下)。
  • 前端会把令牌临时存储在某处。
  • 用户在前端中点击跳转到前端应用的其他部分。
  • 前端需要从 API 获取更多数据。
    • 但该端点需要身份验证。
    • 因此,为了与我们的 API 进行身份验证,它会发送一个 Authorization 请求头,值为 Bearer 加上令牌。
    • 如果令牌内容是 foobarAuthorization 请求头的内容就是:Bearer foobar

FastAPIOAuth2PasswordBearer

FastAPI 在不同抽象层级提供了多种安全工具。

本示例将使用 OAuth2Password 流程并配合 Bearer 令牌,通过 OAuth2PasswordBearer 类来实现。

/// info | 信息

“Bearer” 令牌并非唯一选项。

但它非常适合我们的用例。

对于大多数用例,它也可能是最佳选择,除非你是 OAuth2 专家,并明确知道为何其他方案更适合你的需求。

在那种情况下,FastAPI 同样提供了相应的构建工具。

///

创建 OAuth2PasswordBearer 类实例时,需要传入 tokenUrl 参数。该参数包含客户端(运行在用户浏览器中的前端)用来发送 usernamepassword 以获取令牌的 URL。

{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}

/// tip | 提示

这里的 tokenUrl="token" 指向的是尚未创建的相对 URL token,等价于 ./token

因为使用的是相对 URL若你的 API 位于 https://example.com/,它将指向 https://example.com/token;若你的 API 位于 https://example.com/api/v1/,它将指向 https://example.com/api/v1/token

使用相对 URL 很重要,这能确保你的应用在诸如使用代理{.internal-link target=_blank}等高级用例中依然正常工作。

///

这个参数不会创建该端点/路径操作,而是声明客户端应使用 /token 这个 URL 来获取令牌。这些信息会用于 OpenAPI进而用于交互式 API 文档系统。

我们很快也会创建对应的实际路径操作。

/// info | 信息

如果你是非常严格的 “Pythonista”可能不喜欢使用参数名 tokenUrl 而不是 token_url

这是因为它使用了与 OpenAPI 规范中相同的名称。这样当你需要深入了解这些安全方案时,可以直接复制粘贴去查找更多信息。

///

oauth2_scheme 变量是 OAuth2PasswordBearer 的一个实例,同时它也是“可调用”的。

可以像这样调用:

oauth2_scheme(some, parameters)

因此,它可以与 Depends 一起使用。

使用

现在你可以通过 Dependsoauth2_scheme 作为依赖传入。

{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}

该依赖会提供一个 str,赋值给路径操作函数的参数 token

FastAPI 会据此在 OpenAPI 架构(以及自动生成的 API 文档)中定义一个“安全方案”。

/// info | 技术细节

FastAPI 之所以知道可以使用(在依赖中声明的)OAuth2PasswordBearer 在 OpenAPI 中定义安全方案,是因为它继承自 fastapi.security.oauth2.OAuth2,而后者又继承自 fastapi.security.base.SecurityBase

所有与 OpenAPI以及自动 API 文档)集成的安全工具都继承自 SecurityBase,这就是 FastAPI 能将它们集成到 OpenAPI 的方式。

///

它做了什么

它会在请求中查找 Authorization 请求头,检查其值是否为 Bearer 加上一些令牌,并将该令牌作为 str 返回。

如果没有 Authorization 请求头,或者其值不包含 Bearer 令牌,它会直接返回 401 状态码错误(UNAUTHORIZED)。

你甚至无需检查令牌是否存在即可返回错误;只要你的函数被执行,就可以确定会拿到一个 str 类型的令牌。

你已经可以在交互式文档中试试了:

我们还没有验证令牌是否有效,但这已经是一个良好的开端。

小结

只需增加三四行代码,你就已经拥有了一种初步的安全机制。