使用.NET Core 3.0实现JWT身份验证和Swagger

67

我正在使用.NET Core 3.0开发一些Web API,并希望将其与SwashBuckle.Swagger集成。 在没有JWT身份验证的情况下,它运行正常,但是当我添加JWT身份验证时,它并不像我期望的那样工作。 为了实现这一点,我添加了下面的代码:

services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web API", Version = "v1" });
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey
        });
    });
在添加了AddSecurityDefinition函数后,我能看到“授权”按钮,当我点击它时,会看到下面的表单:enter image description here 然后我输入Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh。在完成后,我期望当我从Swagger向Web API发送请求时,在请求头中能够看到authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh,但是授权并没有添加到请求头中。我正在使用Swashbuckle.Swagger(5.0.0-rc3)。请注意,有许多示例在.NET Core 2.0上运行良好,但最新版本的Swashbuckle Swagger功能已更改,因此我无法使用这些示例。

可能是Swashbuckle .NET Core 2中JWT承载人的授权的重复问题。 - Helen
4
你提到的链接中没有答案。此外,.net core 3.0 稍有不同。 - Nick Mehrdad Babaki
答案是在链接问题的答案中所解释的,添加.AddSecurityRequirement(全局)或.Security(操作级别)-。AddSecurityDefinition单独是不够的。 - Helen
我添加了,但是没有任何变化。我认为这就是为什么它没有被选为答案的原因。 - Nick Mehrdad Babaki
我最近在另一个问题中回答了这个问题,请看这里:https://dev59.com/QVMI5IYBdhLWcg3wcK_K#57872872 - Pavlos
7个回答

145

经过一番研究,我最终在这里找到了答案。

在看到这个页面之前,我知道应该在AddSecurityDefinition之后使用AddSecurityRequirement,因为有很多示例,但在.NET Core 3.0上,函数参数发生了变化,这是一个问题。

顺便说一句,最终的答案如下:

services.AddSwaggerGen(c =>
{
  c.SwaggerDoc("v1", new OpenApiInfo { 
    Title = "My API", 
    Version = "v1" 
  });
  c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
    In = ParameterLocation.Header, 
    Description = "Please insert JWT with Bearer into field",
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey 
  });
  c.AddSecurityRequirement(new OpenApiSecurityRequirement {
   { 
     new OpenApiSecurityScheme 
     { 
       Reference = new OpenApiReference 
       { 
         Type = ReferenceType.SecurityScheme,
         Id = "Bearer" 
       } 
      },
      new string[] { } 
    } 
  });
});

21
这很有效。提示:在实际令牌之前不要忘记写“Bearer”。而且有点烦人的是,无论你在文本框中写什么,swagger总是说已授权...谢谢! - CodeHacker
3
此处呈现的代码无需在令牌前输入Bearer。 https://www.thecodebuzz.com/jwt-authorization-token-swagger-open-api-asp-net-core-3-0/ - Vítor Neil Avelino
1
没有 c.swaggerDoc(..),它在 .NET Core 5.0/6.0 和 Swashbuckle 上运行得很好!谢谢你的分享! - Benyamin Limanto
1
谢谢,这对我也有效。但需要在文本框中添加“Bearer”+ JWT令牌。 - Chamath Viduranga

36

如果您正在使用Swagger 3.0,则它有内置的支持JWT身份验证。

您需要在OpenApiSecurityScheme中使用ParameterLocation.Header、SecuritySchemeType.Http、Bearer和JWT,如下所示。

之后,您就不需要在Bearer {token}格式中指定令牌。只需指定令牌,安全方案将自动将其应用于标头。

// Bearer token authentication
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
    Name = "Bearer",
    BearerFormat = "JWT",
    Scheme = "bearer",
    Description = "Specify the authorization token.",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("jwt_auth", securityDefinition);

// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
    Reference = new OpenApiReference()
    {
        Id = "jwt_auth",
        Type = ReferenceType.SecurityScheme
    }
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
    {securityScheme, new string[] { }},
};
c.AddSecurityRequirement(securityRequirements);

输入图像描述


2
非常感谢!在很多没有对我起作用的帖子之后,这个方法成功了!! - Matt Casto

23
在被接受的答案中,需要在实际令牌前面写上“Bearer ”。 一种类似的方法是可以跳过输入"Bearer ",如下所示:
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Example API", Version = "v1" });

c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.Http,
    BearerFormat = "JWT",
    In = ParameterLocation.Header,
    Scheme = "bearer",
    Description = "Please insert JWT token into field"
});

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

在这里,只需要粘贴JWT令牌即可使其工作。


14

这里是针对Swashbuckle.AspNetCore 5.3.2更新的解决方案,已与IdentityServer4集成,使用Bearer Token保护API。

ConfigureServices()方法中:

services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    options.AddSecurityDefinition("Bearer", SecuritySchemes.BearerScheme(Configuration));
    options.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        { SecuritySchemes.OAuthScheme, new List<string>() }
    });
});
Configure()方法中:
        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/My.Api/swagger/v1/swagger.json", "My API V1");
            options.OAuthClientId(Clients.TestClient);
            options.OAuthAppName("My Api - Swagger");
            options.OAuthClientSecret(Configuration["TestClientSecret"]);
        });

internal static class SecuritySchemes
{
    public static OpenApiSecurityScheme BearerScheme(IConfiguration config) => new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Description = "Standard authorisation using the Bearer scheme. Example: \"bearer {token}\"",
        In = ParameterLocation.Header,
        Name = "Authorization",
        Scheme = "Bearer",
        OpenIdConnectUrl = new System.Uri($"{config["TokenServerUrl"]}.well-known/openid-configuration"),
        BearerFormat = "JWT",
        Flows = new OpenApiOAuthFlows
        {
            Password = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new System.Uri($"{config["TokenServerUrl"]}connect/authorize"),
                Scopes = new Dictionary<string, string>
                    {
                        { Scopes.Api, "My Api" }
                    },
                TokenUrl = new System.Uri($"{config["TokenServerUrl"]}connect/token")
            }
        }
    };

    public static OpenApiSecurityScheme OAuthScheme => new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference
        {
            Type = ReferenceType.SecurityScheme,
            Id = "Bearer"
        },
        Scheme = "oauth2",
        Name = "Bearer",
        In = ParameterLocation.Header,

    };
}

1
这真是救命稻草。它还适用于隐式流,我在流设置中将密码更改为隐式。非常感谢你! - Larsbj
4
好的,这是唯一能为我工作的例子。我简直不敢相信他们把这搞得这么难。 - The Muffin Man

4
如果有人正在使用NSwag并在搜索解决方案后来到这里,下面是官方文档的链接。 启用NSwag JWT身份验证 PS:我知道原问题是关于SwashBuckle的,但谷歌搜索NSwag时会先展示这个链接。

4

如果您不想手动添加令牌,并且希望在向身份服务器传递clientId的同时可以选择范围,可以添加类似以下内容的内容。

我已经使用了隐式流,但是您可以使用以下机制配置任何流程:

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme()
{
  Flows = new OpenApiOAuthFlows
  {
    Implicit = new OpenApiOAuthFlow
    {                            
      AuthorizationUrl = new Uri("http://localhost"),
      TokenUrl = new Uri("http://localhost"),
      Scopes = new Dictionary<string, string>
      {
        { "Foundation API", "FoundationApi" }
      }
    }
  },
  In = ParameterLocation.Header,                    
  Name = "Authorization",
  Type = SecuritySchemeType.OAuth2                    
});

输出结果将如下所示:

enter image description here


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接