Image

在先前的 菜雞新訓記 (4): 使用 Swagger 來自動產生簡單好看可測試的 API 文件吧 中,我們介紹了在 .net Core 環境使用 Swashbuckle 套件來產生 Swagger 文檔,並且直接在 Swagger UI 中呼叫 API 來進行測試。

但很多時候,我們的 API 會需要先驗證才能使用,例如在 Header 傳遞 Token 來驗證身分等等。這時候 Swagger UI 就會整個廢掉,打了都會出錯,很不方便。

因此這篇文章就紀錄一下如何在 Swagger UI 上加入 Authorize Token 的傳遞,讓 Swagger UI 在需要身分驗證的環境也能直接呼叫使用。

環境佈置

首先範例專案直接參考 The Will Will Web 的這篇 如何在 ASP.NET Core 3 使用 Token-based 身分驗證與授權 (JWT),捏一個需要登入取得 JWT Token,然後將 Token 放到 Header 的 Authorize 才能查詢資料的專案。

專案的大致狀況和目前 Swagger UI 如下,有登入和查詢兩支方法:

Image

那我們沒有登入的情況直接呼叫查詢方法就會報錯:

Image

登入的話就能拿到 Token:

Image

用 Postman 試試看把 Token 掛到 Authorization,查詢就可以成功:

Image

但是我們的 Swagger 還沒有提供能放 Authorization Token 的地方,這樣用起來就會 Hen 不方便。

因此目標就是:可以將這組 Token 放到 Header 裡,讓查詢方法不要報錯。讓我們開始吧!

加入 Authorize 設置

首先讓我們先找到註冊 Swagger 產生器的地方,以先前的 Swagger 介紹文為例的話,會是在 Startup.csConfigureServices 裡的 AddSwaggerGen

裡面可能已經有包含 API 簡介等欄位,例如:

// 註冊 Swagger 產生器
services.AddSwaggerGen(options =>
{
    // API 服務簡介
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "JWT Demo",
        Description = "菜雞嘗試 JWT 的範例 API",
        TermsOfService = new Uri("https://igouist.github.io/"),
        Contact = new OpenApiContact
        {
            Name = "Igouist",
            Email = string.Empty,
            Url = new Uri("https://igouist.github.io/about/"),
        }
    });

    // 讀取 XML 檔案產生 API 說明
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    options.IncludeXmlComments(xmlPath);
});

首先讓我們用 Security Scheme 來告訴 Swagger 我們的驗證資訊吧。在 AddSwaggerGen 中加上 AddSecurityDefinition

options.AddSecurityDefinition("Bearer", 
    new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT Authorization"
    });

加了之後就能在 Swagger UI 看見我們的 Authorize 按鈕囉:

Image

點開就會看到我們上面定義的內容:

Image

不過現在還不會作用,我們還得讓全部的呼叫都自動加上這個 Token 才行。接著在 AddSwaggerGen 中加上 AddSecurityRequirement,並且讓他去抓我們前面設定好 “Bearer” 的 SecurityScheme:

options.AddSecurityRequirement(
    new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            new string[] {}
        }
    });

注意 Id 要和我們上一步加入的 Scheme 一致呦。

補充:OpenApiSecurityRequirement 是一個 Dictionary,所以中間那層 {} 不要忘囉

加完之後現在的 AddSwaggerGen 大概是這個樣子的:

// 註冊 Swagger 產生器
services.AddSwaggerGen(options =>
{
    // API 服務簡介
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "JWT Demo",
        Description = "菜雞嘗試 JWT 的範例 API",
        TermsOfService = new Uri("https://igouist.github.io/"),
        Contact = new OpenApiContact
        {
            Name = "Igouist",
            Email = string.Empty,
            Url = new Uri("https://igouist.github.io/about/"),
        }
    });

    // Authorization
    options.AddSecurityDefinition("Bearer", 
    new OpenApiSecurityScheme
        {
            Name = "Authorization",
            Type = SecuritySchemeType.ApiKey,
            Scheme = "Bearer",
            BearerFormat = "JWT",
            In = ParameterLocation.Header,
            Description = "JWT Authorization"
        });

    options.AddSecurityRequirement(
        new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    }
                },
                new string[] {}
            }
        });

    // 讀取 XML 檔案產生 API 說明
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    options.IncludeXmlComments(xmlPath);
});

完工測試

接著就讓我們啟動試試吧!

首先讓我們把登入的 Token 放到 Authorization 按鈕的欄位裡,不要忘記加上 Bearer:

Image

Image

加入之後就 Close,讓我們打看看查詢的方法:

Image

可以看到成功拿到值啦!

從開發工具也可以看到 Header 的確有加上 Bearer Token 了:

Image

大功告成,打完收工!

參考資料