You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为不同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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:53:10