3. 安全方案定义:securitySchemes 详解
在 OpenAPI 契约中,securitySchemes 是定义后端鉴权方式的“注册中心”。它位于 components 对象下,声明所有可用的安全方案类型,再由全局或路径级的 security 字段引用。本章逐一拆解五种主流方案:API Key、HTTP Basic、Bearer Token、OAuth2 和 OpenID Connect。
3.1 securitySchemes 结构总览
一个典型的 securitySchemes 定义如下:
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
BasicAuth:
type: http
scheme: basic
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
OAuth2Auth:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/authorize
tokenUrl: https://auth.example.com/token
scopes:
read: 读取资源
write: 写入资源
OpenIDConnectAuth:
type: openIdConnect
openIdConnectUrl: https://auth.example.com/.well-known/openid-configuration
关键原则:每个安全方案必须有一个唯一的键名(如
ApiKeyAuth),后续在 security 字段中通过该键名引用。类型决定了必须提供的其他属性。3.2 五种安全方案对比
| 方案类型 | type 值 | 核心属性 | 典型场景 |
|---|---|---|---|
| API Key | apiKey |
in(header/query/cookie)、name |
服务间简单鉴权、第三方 API 调用 |
| HTTP Basic | http + scheme: basic |
scheme |
遗留系统、快速原型 |
| Bearer Token | http + scheme: bearer |
bearerFormat(可选) |
JWT 鉴权、OAuth2 访问令牌 |
| OAuth2 | oauth2 |
flows(授权码/隐式/密码/客户端凭证) |
用户授权、第三方登录 |
| OpenID Connect | openIdConnect |
openIdConnectUrl |
身份认证 + 用户信息获取 |
3.3 API Key 方案详解
API Key 是最简单的鉴权方式,通过一个预共享的密钥字符串识别调用方。OpenAPI 中需指定密钥的传输位置和名称。
components:
securitySchemes:
ApiKeyHeader:
type: apiKey
in: header
name: X-API-Key
ApiKeyQuery:
type: apiKey
in: query
name: api_key
ApiKeyCookie:
type: apiKey
in: cookie
name: session_id
- in: header — 密钥放在 HTTP 请求头中,如
X-API-Key: abc123。 - in: query — 密钥作为 URL 查询参数,如
?api_key=abc123(不推荐,易泄露)。 - in: cookie — 密钥放在 Cookie 中,适用于浏览器端会话。
安全提示:API Key 本身不提供身份验证(仅识别调用方),且容易在日志或 URL 中泄露。生产环境建议配合 HTTPS 使用,并定期轮换密钥。
3.4 HTTP Basic 与 Bearer Token
两者都属于 type: http,通过 scheme 字段区分。
HTTP Basic
客户端将 用户名:密码 进行 Base64 编码后放入 Authorization 头:
Authorization: Basic base64(username:password)
OpenAPI 定义:
components:
securitySchemes:
BasicAuth:
type: http
scheme: basic
Bearer Token
客户端将令牌直接放入 Authorization 头,格式为 Bearer <token>:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
OpenAPI 定义:
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT # 可选,说明令牌格式
对比:Basic 每次请求都携带明文密码(仅 Base64 编码,非加密),安全性低;Bearer Token 通常配合 JWT 使用,可携带声明和过期时间,更安全灵活。
3.5 OAuth2 流程详解
OAuth2 是授权框架,OpenAPI 支持四种授权流程(flows)。每个流程需定义授权端点、令牌端点及作用域。
| 流程类型 | flow 键 | 必需端点 | 适用场景 |
|---|---|---|---|
| 授权码模式 | authorizationCode |
authorizationUrl + tokenUrl |
服务端 Web 应用、有后端的移动应用 |
| 隐式模式 | implicit |
authorizationUrl |
纯前端 SPA(已不推荐) |
| 密码模式 | password |
tokenUrl |
受信任的第一方应用 |
| 客户端凭证模式 | clientCredentials |
tokenUrl |
服务间通信、无用户场景 |
示例:授权码模式定义
components:
securitySchemes:
OAuth2Auth:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/oauth/authorize
tokenUrl: https://auth.example.com/oauth/token
scopes:
read: 读取用户资料
write: 修改用户资料
admin: 管理权限
作用域(scopes)是 OAuth2 的核心概念,用于限制令牌的权限范围。在 OpenAPI 中,
security 字段可指定所需作用域,如 security: [OAuth2Auth: [read, write]]。3.6 OpenID Connect 方案
OpenID Connect(OIDC)在 OAuth2 之上增加身份认证层。OpenAPI 中只需提供 OIDC 发现 URL,客户端可自动获取授权端点、令牌端点、公钥等信息。
components:
securitySchemes:
OIDCAuth:
type: openIdConnect
openIdConnectUrl: https://auth.example.com/.well-known/openid-configuration
OIDC 返回的 ID Token(通常为 JWT)包含用户身份声明(sub、name、email 等),后端可据此完成用户认证。
与 OAuth2 的区别:OAuth2 关注授权(“你能访问什么”),OIDC 关注认证(“你是谁”)。OIDC 是 OAuth2 的超集,常用于单点登录(SSO)。
3.7 安全方案选择决策流程
下图展示了根据场景选择安全方案的决策路径:
3.8 安全方案在契约中的引用
定义好 securitySchemes 后,通过全局或路径级的 security 字段引用:
# 全局安全(所有接口默认)
security:
- BearerAuth: []
# 路径级覆盖(仅 /admin 需要 OAuth2 作用域)
paths:
/admin/users:
get:
security:
- OAuth2Auth: [admin]
responses:
'200':
description: 用户列表
注意:路径级
security 会覆盖全局设置。如果某个接口不需要鉴权,可显式设置为 security: []。3.9 常见错误与校验规则
| 错误类型 | 示例 | 正确做法 |
|---|---|---|
| 缺少必需属性 | type: apiKey 未指定 in |
必须指定 in 和 name |
| OAuth2 流程拼写错误 | authorization_code(下划线) |
使用驼峰 authorizationCode |
| 作用域未定义 | security: [OAuth2Auth: [read]] 但 flows 中未声明 read |
在 flows.scopes 中预先定义所有作用域 |
| Bearer 格式不匹配 | bearerFormat: JWT 但实际返回 opaque token |
保持 bearerFormat 与实际令牌格式一致 |
契约校验要点:使用 OpenAPI 校验工具(如 Spectral、Redocly CLI)时,应启用安全方案相关规则,确保每个
security 引用都对应已定义的 securitySchemes,且 OAuth2 作用域在 flows 中已声明。