安全简介:OAuth2、密码流与 JWT
本教程共 50 篇 · 第 26 篇 · 更新于 2026-08-12 · 约 7 分钟阅读
本节目标:搞懂”认证”和”授权”有什么不同,弄明白 OAuth2 密码流怎么让前端拿到令牌,以及 JWT 长什么样、为什么接口爱用令牌。
26-1 先分清两件事:认证与授权
很多人把”登录”和”有权限”混为一谈。其实它们是两个动作,名字也很像,但含义不同。
**认证(authentication)**回答的问题是”你是谁”。它要确认访问者确实是他声称的那个人。比如你输入账号密码,系统核对通过,这就完成了认证。
**授权(authorization)**回答的问题是”你能做什么”。在确认你是谁之后,系统再决定把哪些功能对你开放。比如你是普通用户,就不能删全站数据;你是管理员,才可以。
一句话记法:认证是”验明正身”,授权是”发放权限”。先认证再授权,顺序不能反。
Note英文里这两个词也只差一个字母:authentication(认证)和 authorization(授权)。初学时容易看错,写代码时尤其要分清。
在实际项目里,认证和授权常常一起出现。FastAPI 把这两件事都交给你用依赖注入(Depends)来写,逻辑可以放在同一个地方,后面几章会一步步讲。
26-2 为什么接口需要”安全”这套东西
网站和手机 App 通常是分开的。前端(网页或 App)在一个地方,后端接口在另一个地方。前端要代表用户去后端要数据,就必须先证明”我是这个用户”。
最朴素的想法是:每次请求都带上账号密码。这很危险。密码在网络里反复传,被截获一次就完蛋;而且后端每次都要查库比对密码,既慢又容易泄露。
聪明的做法是:只登录一次,换一张”临时门票”。这张门票就是令牌(token)。之后前端每次请求只亮出令牌,后端验一下门票有效,就放行。
OAuth2 就是一套关于”怎么发门票、怎么用门票”的规范。FastAPI 自带一组工具,让你不用啃完整规范也能用上它。
26-3 OAuth2 是什么,又不是什么
OAuth2 是一份规范,定义了好几种处理认证和授权的方式,规范里管这些方式叫”流(flow)“。它覆盖的场景很广,包括”用微信登录第三方网站”这种第三方授权。
你每天见的”用 Google 登录""用 GitHub 登录”,底层就是 OAuth2 的某一种流。这些流让一个系统替另一个系统确认用户身份。
OAuth2 本身不规定通信怎么加密。它假设你的网站已经上了 HTTPS。加密交给 HTTPS,OAuth2 只管”发令牌”的逻辑。所以上线前一定要配好 HTTPS,这是安全的前提。
Tip新手最常见的是”密码流(password flow)“。它适合你自己的前端登录你自己的后端。因为你控制着前端,可以放心让它收账号密码。本章后面就讲它。
26-4 密码流:一次登录的全过程
密码流的核心思路,可以拆成下面几步,理解它就理解了大半:
- 用户在网页里输入账号和密码,敲回车。
- 前端把账号、密码发给后端一个专门换令牌的地址(约定叫
/token)。 - 后端核对账号密码,正确就发回一个令牌字符串。
- 前端把令牌临时存起来,比如存在浏览器本地存储。
- 之后用户点别的页面,前端要去后端拿数据。
- 这次前端在请求头里带上令牌,写法固定是
Authorization: Bearer 令牌内容。 - 后端看到这个头,验一下令牌没问题,就返回数据。
注意第 6 步:密码只在第 2 步出现一次。后面所有请求都只靠令牌,密码不再乱跑,安全很多。
Note令牌通常有过期时间,比如 30 分钟。过期后前端得让用户重新登录换新的。这样就算令牌被偷,小偷也用不了太久。
26-5 Bearer 与 WWW-Authenticate 头
前面说前端要带 Authorization 头。它的标准写法是:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.yyyy
Bearer 是个英文词,意思是”持有者”。它表达的逻辑是:谁拿着这个令牌,谁就是合法用户。所以叫”持有者令牌”。
反过来,如果后端发现请求里根本没有 Authorization 头,或者格式不对,它会直接回一个 401 状态码(未认证)。401 的意思是”没提供凭据或凭据无效”,和 403(已登录但没权限)是两回事。按规范,这种 401 响应还要带一个 WWW-Authenticate 头,内容写 Bearer,提示客户端”这里要用 Bearer 令牌来认证”。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
FastAPI 的 OAuth2PasswordBearer 会自动处理这些细节。没带令牌时它直接给你 401,你都不用手动判断。
26-6 JWT 长什么样:三段结构
最常用的令牌是 JWT(JSON Web Token)。它看起来是一长串没有空格的字符,用两个点 . 分成三段:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huZG9lIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这三段分别是:
- 第一段 header(头):说明令牌类型和下一条用什么算法签名,是 base64 编码的 JSON。
- 第二段 payload(载荷):真正放数据的地方,比如用户 id、过期时间,也是 base64 编码的 JSON。
- 第三段 signature(签名):用密钥对前两段算出来的签名,用来防篡改。
前两段只是编码,不是加密,谁都能解码看到内容。但第三段签名保证了:只要有人改了前两段,签名就对不上,后端一验就知道是假令牌。
所以 JWT 是”可读取但不可伪造”。你可以在 payload 里放用户身份,后端靠签名确认它是自己发的。
26-7 为什么用令牌,而不是每次都发密码
把账号密码换成令牌,好处很清楚:
- 密码少暴露。密码只在登录那一刻发出去,之后全用令牌,被截获的风险小。
- 可过期。令牌设个短时效,丢了也用不久;密码一般长期不变,丢了很麻烦。
- 后端好扩展。验令牌不需要每次查用户库,甚至不需要访问数据库,多个服务都能直接验,适合分布式。
- 能带信息。JWT 的 payload 能塞用户身份,后端解码即用,少一次数据库往返。
Tip想亲手看 JWT 怎么拆开,可以打开 jwt.io 把上面那段粘进去,左边是原始串,右边立刻显示三段解码后的内容。建议玩一下加深理解。
26-8 小结与后续路线
这一章建立了一套语言:认证验身份,授权给权限;OAuth2 管发令牌;密码流让你自己的前端登录自己的后端;Bearer 是令牌放在请求头里的固定写法;JWT 分头、载荷、签名三段,可读不可伪造。
后面的章节会动手把它全串起来:
- 第 27 章讲密码不能明文存,要用 bcrypt 哈希。
- 第 28 章写
/token登录接口,用 PyJWT 签发 JWT。 - 第 29 章用
OAuth2PasswordBearer保护需要登录才能访问的接口。 - 第 30 章给不同用户分级,用 scopes 做细粒度权限。
- 第 31 章再看 API Key 和 HTTP Basic 这两种更简单的认证方式。
记住一句主线:登录换令牌,请求带令牌,后端验令牌。整套安全机制就是围着这三句话转。