NET Core 3.0的JWT身份验证和Swagger


10

我正在使用.Net core 3.0开发一些Web Api,并希望将其与SwashBuckle.Swagger集成。它工作正常,但是当我添加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功能后,我可以看到“授权”按钮,当我单击它时,会看到以下表单: 在此处输入图片说明

然后输入Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh,完成后authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh,当我从Swagger向Web Api发送请求时,我希望在请求的标头中看到该内容。但是授权未添加到请求标头中。我正在使用SwashBuckle.Swagger(5.0.0-rc3)。请注意,有许多示例可以在.net core 2.0上正常运行,但是Swashbuckle摇摇欲坠的功能在最新版本上已更改,因此我无法使用该示例。



您提到的链接上没有答案。.net core 3.0也略有不同。
Mehrdad Babaki

答案是添加.AddSecurityRequirement(全局)或.Security(在操作级别)-如链接问题的答案中所述。AddSecurityDefinition单靠光棍是不够的。
海伦

我添加了,但没有任何改变。我认为这就是为什么不选择它作为答案的原因。
Mehrdad Babaki

我最近在另一个问题上回答了这个问题,请看这里:stackoverflow.com/a/57872872/3952573
Pavlos

Answers:


33

经过研究,我终于在这里找到了答案

在看到此页面之前,我知道我应该因为很多示例而使用AddSecurityRequirementafter AddSecurityDefinition,但是在.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[] { } 
    } 
  });
});

非常感谢,这是做工精细与我
阿纳斯铝Qudah

2
提示:不要忘记在实际令牌之前写“ Bearer”。不管您在文本框中写什么,大摇大摆总是说授权,这有点令人讨厌。谢谢!
CodeHacker

这适用于网络核心3和大摇大摆
ericpap

拯救生命的人拯救世界。您救了我的命;-) thx
Vahid Farahmandian

6

如果您使用的是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);

在此处输入图片说明


谢谢!在很多帖子对我不起作用之后,此方法成功了!!
Matt Casto

2

如果您不想手动添加令牌,并且希望范围是可选的以及将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                    
});

输出将如下所示:

在此处输入图片说明


1

这是针对Swashbuckle.AspNetCore 5.3.2更新的解决方案,该解决方案与IdentityServer4集成,具有使用Bearer令牌保护的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,

    };
}

这可以节省生命。它也适用于隐式流程,其中我在“流程”设置中将“密码”更改为“隐式”。非常感谢你!
Larsbj

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.