如何为不同Swashbuckle(Swagger)文档设置不同授权范围?
问题:为Swashbuckle的多个Swagger文档配置不同OAuth2授权范围
我有一个Web API,会生成两个Swashbuckle(Swagger)文档,分别为Doc A和Doc B。我希望为每个文档设置不同的授权范围:
- Doc A - scopeA
- Doc B - scopeA, scopeB
现有代码如下:
services.AddSwaggerGen(c => { var authorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("abc"), TokenUrl = new Uri("xyz"), // swaggerSettings.Scopes is Dictionary<string, string>, containing "scope-description" pairs Scopes = swaggerSettings.Scopes }; c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = authorizationCode } }); }) ... app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/swagger.json", "Doc A"); }); app.UseSwaggerUI(c => { c.RoutePrefix = "swagger/anotherDoc"; c.SwaggerEndpoint("/swagger/another/swagger.json", "Doc B"); });
目前指定的授权范围(即SecurityDefinition)会被两个文档共用,不清楚如何为每个文档单独指定不同的授权范围,请问是否有可行的实现方式?
解决方案
要为不同Swagger文档配置独立的OAuth2授权范围,有两种可行的实现方式:
方式1:为每个文档单独定义SecurityDefinition(推荐)
通过SwaggerDoc定义多个文档,并为每个文档配置专属的SecurityDefinition,再用自定义DocumentFilter将安全要求绑定到对应文档。
步骤1:配置SwaggerGen
services.AddSwaggerGen(c => { // 定义Doc A文档 c.SwaggerDoc("v1", new OpenApiInfo { Title = "Doc A", Version = "v1" }); // 为Doc A配置专属OAuth2范围 var docAFlow = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("abc"), TokenUrl = new Uri("xyz"), Scopes = new Dictionary<string, string> { { "scopeA", "Scope A的描述" } } }; c.AddSecurityDefinition("oauth2-docA", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = docAFlow } }); // 绑定Doc A的安全要求 c.DocumentFilter<SecurityRequirementsFilter>("oauth2-docA", "Doc A"); // 定义Doc B文档 c.SwaggerDoc("v2", new OpenApiInfo { Title = "Doc B", Version = "v2" }); // 为Doc B配置专属OAuth2范围 var docBFlow = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("abc"), TokenUrl = new Uri("xyz"), Scopes = new Dictionary<string, string> { { "scopeA", "Scope A的描述" }, { "scopeB", "Scope B的描述" } } }; c.AddSecurityDefinition("oauth2-docB", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = docBFlow } }); // 绑定Doc B的安全要求 c.DocumentFilter<SecurityRequirementsFilter>("oauth2-docB", "Doc B"); }); // 自定义文档筛选器:仅为指定文档添加对应安全要求 public class SecurityRequirementsFilter : IDocumentFilter { private readonly string _schemeName; private readonly string _targetDocTitle; public SecurityRequirementsFilter(string schemeName, string targetDocTitle) { _schemeName = schemeName; _targetDocTitle = targetDocTitle; } public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { // 仅处理目标文档 if (swaggerDoc.Info.Title != _targetDocTitle) return; swaggerDoc.SecurityRequirements.Add(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = _schemeName } }, new List<string>() // 若需强制指定范围,可传入具体列表如new List<string>{"scopeA"} } }); } }
步骤2:配置SwaggerUI
为每个UI实例绑定对应文档,并配置OAuth2客户端信息:
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Doc A"); c.OAuthClientId("你的客户端ID"); c.OAuthAppName("Doc A API"); c.OAuthScopeSeparator(" "); }); app.UseSwaggerUI(c => { c.RoutePrefix = "swagger/anotherDoc"; c.SwaggerEndpoint("/swagger/v2/swagger.json", "Doc B"); c.OAuthClientId("你的客户端ID"); c.OAuthAppName("Doc B API"); c.OAuthScopeSeparator(" "); });
方式2:动态修改单一SecurityDefinition的范围
如果不想定义多个SecurityDefinition,可通过DocumentFilter在文档生成时,根据当前文档动态调整Scopes:
services.AddSwaggerGen(c => { // 定义两个文档 c.SwaggerDoc("v1", new OpenApiInfo { Title = "Doc A", Version = "v1" }); c.SwaggerDoc("v2", new OpenApiInfo { Title = "Doc B", Version = "v2" }); // 配置基础OAuth2框架 var baseFlow = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("abc"), TokenUrl = new Uri("xyz") }; c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = baseFlow } }); // 添加动态范围筛选器 c.DocumentFilter<DynamicScopeFilter>(); }); // 自定义筛选器:根据文档标题调整授权范围 public class DynamicScopeFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { var oauthScheme = swaggerDoc.Components.SecuritySchemes .FirstOrDefault(s => s.Key == "oauth2").Value; if (oauthScheme == null) return; switch (swaggerDoc.Info.Title) { case "Doc A": oauthScheme.Flows.AuthorizationCode.Scopes = new Dictionary<string, string> { { "scopeA", "Scope A的描述" } }; break; case "Doc B": oauthScheme.Flows.AuthorizationCode.Scopes = new Dictionary<string, string> { { "scopeA", "Scope A的描述" }, { "scopeB", "Scope B的描述" } }; break; } } }
SwaggerUI配置同方式1,每个UI实例会自动加载对应文档的范围。
注意事项
- 确保每个Swagger文档的
Title或Version唯一,以便筛选器正确区分 - 若API端点通过
[Authorize(Scope = "...")]指定了范围,可结合OperationFilter进一步细化每个接口的授权范围关联
内容的提问来源于stack exchange,提问作者Koji
相关产品推荐
相关产品推荐

