使用 .NET Core 3.0 进行 JWT 身份验证和 Swagger

Posted

技术标签:

【中文标题】使用 .NET Core 3.0 进行 JWT 身份验证和 Swagger【英文标题】:JWT Authentication and Swagger with .NET Core 3.0 【发布时间】:2020-01-30 09:57:06 【问题描述】:

我正在使用 .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。完成后,当我从 Swagger 向 Web API 发送请求时,我希望在请求的标头中看到 authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh,但未将授权添加到请求标头中。我正在使用 SwashBuckle.Swagger(5.0.0-rc3)。请注意,有许多示例在 .NET Core 2.0 上运行良好,但 Swashbuckle 招摇功能在最新版本上发生了变化,因此我无法使用这些示例。

【问题讨论】:

Authorization for JWT bearer in Swashbuckle .NET Core 2的可能重复 在您提到的链接上没有答案。 .net core 3.0 也略有不同。 答案是添加.AddSecurityRequirement(全局)或.Security(在操作级别) - 如链接问题的答案中所述。仅AddSecurityDefinition 是不够的。 我添加了但没有任何改变。我认为这就是为什么它没有被选为答案。 我最近在另一个问题上回答了这个问题,请看这里:***.com/a/57872872/3952573 【参考方案1】:

经过一番研究,我终于找到了答案here

在看到这个页面之前,我知道我应该在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[]   
     
  );
);

【讨论】:

这有效.. 提示:不要忘记在实际令牌之前写“Bearer”。而且不管你在文本框中写什么,大摇大摆总是说授权有点烦人......谢谢! 拯救生命的人就是拯救世界的人。你救了我的命 ;-) thx 这里展示的代码不需要在token前输入Bearer:thecodebuzz.com/… 没有c.swaggerDoc(..),它在带有花饰扣的.NET core 5.0/6.0 上就像魅力一样!谢谢分享!【参考方案2】:

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

【讨论】:

谢谢!在许多对我不起作用的帖子之后,这种方法成功了!【参考方案3】:

在接受的答案中,“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 令牌即可。

【讨论】:

【参考方案4】:

这是针对 Swashbuckle.AspNetCore 5.3.2 更新的解决方案,与 IdentityServer4 集成,API 使用 Bearer 令牌进行保护。

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,

    ;

【讨论】:

这是一个救生员。它也适用于我在 Flows 设置中将 Password 更改为 Implicit 的隐式流。非常感谢! 好的,这是唯一对我有用的例子。我无法相信他们让这件事变得如此困难。【参考方案5】:

如果有人在使用 NSwag 并在搜索解决方案后登陆这里,这里是官方文档的链接。

NSwag Enable JWT authentication

PS:我知道最初的问题是针对 SwashBuckle,但 Google 在搜索 NSwag 时也会首先显示此链接。

【讨论】:

【参考方案6】:

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

输出将是这样的:

【讨论】:

【参考方案7】:

在接受答案中,您必须手动将“不记名”附加到令牌,这将产生新问题,Swagger 可以将“不记名”附加到令牌观看以下链接

JWT Authentication and Swagger with .NET Core 3 and 5 YouTube video

【讨论】:

以上是关于使用 .NET Core 3.0 进行 JWT 身份验证和 Swagger的主要内容,如果未能解决你的问题,请参考以下文章

.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联

.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联

ASP.Net Core 3.0 JWT Bearer Token 没有 SecurityTokenValidator 可用

ASP Core 3.0 API 令牌自定义令牌身份验证(不是 jwt!)

如何在 .NET Core 3.0 中替换 AddJwtBearer 扩展

使用 Net Core 2 进行 JWT 远程身份验证时出错