Swashbuckle 10.1.7 如何让 Swagger UI 发送 Bearer Token?
可以保留现有的 OAuth2 implicit flow。先检查生成的 OpenAPI 文档,确认目标操作是否关联了 oauth2 安全方案,以及迁移后的安全方案引用是否绑定了当前 OpenApiDocument。仅调用 AddSecurityDefinition 不会让 Swagger UI 为接口请求附加 Token。
现有材料没有提供 TAuthFilter 的实现和生成的 OpenAPI JSON,暂时无法确定具体故障点。可以按以下步骤检查。
为什么能登录,却没有 Authorization 请求头?
Swagger UI 的授权涉及两个部分:安全方案描述如何取得 Token,安全要求指定哪些操作使用该方案。Authorize 登录成功,只能说明取得 Token 的环节可能已经完成。
Swashbuckle.AspNetCore 10.x 使用 OpenApiSecuritySchemeReference 配置安全要求。官方 10.1.7 示例通过 document 或 context.Document 创建引用,不能只调整旧代码的命名空间。安全方案与安全要求配置
这里的 10.1.7 是 Swashbuckle.AspNetCore 包版本。Swagger UI 是它集成的前端组件,两者的版本号不能混用。组件说明
优先检查 TAuthFilter 中的安全方案引用
保留现有的 AddSecurityDefinition("oauth2", ...) 和 implicit flow 配置。在 TAuthFilter.Apply 中,找到为受保护操作设置 operation.Security 的位置,使用当前文档创建引用:
using Microsoft.OpenApi;
// 放在 Apply(OpenApiOperation operation, OperationFilterContext context)
// 中已经确认该操作需要授权的分支内。
operation.Security = new List<OpenApiSecurityRequirement>
{
new OpenApiSecurityRequirement
{
[new OpenApiSecuritySchemeReference("oauth2", context.Document)]
= new List<string>()
}
};
配置时注意:
"oauth2"必须与AddSecurityDefinition的名称完全一致,包括大小写。- 引用应传入当前的
context.Document。 - 空列表表示此处没有声明具体的必需 scope。如果接口要求特定 scope,应填入实际的 scope 名称,不要直接把授权 policy 名称当作 scope。
这段代码只替换安全要求的构造方式。仍需保留原有的接口授权判断,并正确处理匿名接口。官方的 Operation filter 示例也使用了带 context.Document 的引用。Operation filter 示例
如果整个文档都使用 OAuth2,可以配置全局要求
如果文档中的操作都应使用同一授权方案,可以在现有的 AddSwaggerGen 配置中添加:
options.AddSecurityRequirement(document => new OpenApiSecurityRequirement
{
[new OpenApiSecuritySchemeReference("oauth2", document)]
= new List<string>()
});
全局配置和按操作设置要求的适用范围不同。如果文档中既有公开接口,也有受保护接口,通常更适合继续使用过滤器。
还要检查过滤器是否为操作生成了 security: []。操作级安全要求会覆盖全局配置,空数组会取消该操作继承的全局安全要求。因此,加上全局要求后仍需检查最终文档。OpenAPI 安全要求说明
用生成的文档和实际请求验证
打开 Swagger UI 当前加载的 OpenAPI JSON。默认路径通常是 /swagger/v1/swagger.json;如果项目使用了自定义路径或多个文档,应以页面实际加载的地址为准。
检查以下内容:
components.securitySchemes.oauth2存在,类型为oauth2,并包含正确的flows.implicit.authorizationUrl和 scopes。- 目标操作自身或文档根级存在对应的安全要求,例如:
"security": [
{
"oauth2": []
}
]
- 修改配置后刷新页面,重新完成 Authorize,再从浏览器 Network 面板检查实际的 API 请求。预期请求头为:
Authorization: Bearer <access_token>
如果使用 Swashbuckle 默认页面暴露的 window.ui 实例,还可以在控制台检查 Token 是否已经进入授权状态,而不打印 Token 本身:
const auth = window.ui.authSelectors.authorized().toJS();
console.log({
hasAccessToken: Boolean(auth.oauth2?.token?.access_token),
tokenType: auth.oauth2?.token?.token_type
});
自定义页面可能使用其他实例变量,需要相应调整。如果没有 access_token,应检查 OAuth 回调和授权结果;如果已有 Token 且安全要求正确,可以继续排查自定义请求拦截器、旧文档缓存等因素。Swagger UI 会将 OAuth2 返回的 Token 放入对应方案的授权状态中。授权状态实现
授权数据存储在哪里?
Swagger UI 默认将授权数据保存在当前页面的 JavaScript 状态中。persistAuthorization 默认为 false,不会为了跨刷新保留授权而写入持久化存储。Swagger UI 配置说明
如果需要刷新页面后保留授权,可以在现有的 UI 配置中启用:
app.UseSwaggerUI(options =>
{
// 保留项目原有的 SwaggerEndpoint 和 OAuth 客户端配置。
options.EnablePersistAuthorization();
});
EnablePersistAuthorization() 会把 persistAuthorization 设置为 true。随后,Swagger UI 的默认授权实现会将数据写入当前页面所属 origin 的 localStorage,键名为 authorized。可以在浏览器开发者工具的 Local Storage 中查看。该值可能包含 access token,不要将其复制到日志或问题截图中。Swashbuckle 配置实现、Swagger UI 持久化实现
持久化只控制刷新后的授权保留,不会修复缺失的安全要求,也不会延长 Token 的有效期。
Cookie 与 Bearer Token 可以同时发送吗?
可以。浏览器根据 Cookie 的作用域和请求条件携带 Cookie,Swagger UI 根据操作的安全要求附加 Bearer Token。仅看到 Cookie,不能证明 Swagger UI 已取得并使用 access token。
这次应先修正或确认 TAuthFilter 和生成的 security。无需另加一个手动输入 Token 的 HTTP Bearer 方案来替代现有登录流程,也不应在尚未定位原因时通过拦截器给所有请求硬塞 Token。如果请求跨域且还需要 Cookie,还需核对客户端凭据设置及服务端 CORS 配置;这与 OAuth2 安全方案关联是不同的配置。Swagger UI 网络配置
备注:内容仅供参考。
