使用 JWT Bearer 令牌进行身份验证 Swagger

Posted

技术标签:

【中文标题】使用 JWT Bearer 令牌进行身份验证 Swagger【英文标题】:Authentication Swagger with JWT Bearer token 【发布时间】:2018-08-29 00:21:57 【问题描述】:

我们正在开发一个带有 JWT Bearer 身份验证的 .Net Core 2.1 Web API。应用程序本身将生成并分发要发送到后端的令牌。

虽然我们已经启动并运行了所有内容,即我们可以从 Angular 发送不记名令牌并使用 Postman 对其进行测试,但 Swagger 不会发送不记名令牌。 我们添加了 Swagger 配置以使用 SecurityDefinition,如下所示,我将发布完整的 ConfigureServices 方法:

public void ConfigureServices(IServiceCollection services)
    
        // Add framework services.
        services.AddMvc();
        services.AddCors(options =>
        
            options.AddPolicy("AllowAllOrigins",
                policy => policy.WithOrigins("*").AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
        );
        services.Configure<MvcOptions>(options =>
        
            options.Filters.Add(new CorsAuthorizationFilterFactory("AllowAllOrigins"));
        );

        ServiceInstaller.Install(services, Configuration);

        // api user claim policy
        services.AddAuthorization(options =>
        
            var authorizationPolicy = new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                .RequireAuthenticatedUser().Build();
            options.AddPolicy("Bearer", authorizationPolicy);
        );
        // add identity
        var builder = services.AddIdentityCore<AppUser>(o =>
        
            // configure identity options
            o.Password.RequireDigit = false;
            o.Password.RequireLowercase = false;
            o.Password.RequireUppercase = false;
            o.Password.RequireNonAlphanumeric = false;
            o.Password.RequiredLength = 6;
        );
        builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
        builder.AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

        var keyByteArray = Encoding.ASCII.GetBytes("placekeyhere");
        var signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyByteArray);
        services.AddAuthentication(options =>  options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(
            options =>
            
                options.TokenValidationParameters = new TokenValidationParameters()
                
                    IssuerSigningKey = signingKey,
                    ValidAudience = "Audience",
                    ValidIssuer = "Issuer",
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.FromMinutes(0)
                ;
            );
        // Configure JwtIssuerOptions
        services.Configure<JwtIssuerOptions>(options =>
        
            options.Issuer = "Issuer";
            options.Audience = "Audience";
            options.SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
        );

        // Register the Swagger generator, defining one or more Swagger documents
        services.AddSwaggerGen(c =>
        
            c.SwaggerDoc("v1", new Info  Title = "AppName", Version = "v1" );
            c.OperationFilter<UploadOperation>();
            c.AddSecurityDefinition("Authorization", new ApiKeyScheme
            
                Description =
                    "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer token\"",
                Name = "Authorization",
                In = "header",
                Type = "apiKey",
            );
        );
    

这确实将验证选项添加到屏幕顶部。在配置方法中,我们告诉应用程序实际使用身份验证:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    
        app.UseAuthentication();
        if (env.IsDevelopment())
        
            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseCors();
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (html, JS, CSS, etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>  c.SwaggerEndpoint("/swagger/v1/swagger.json", "AppName"); );
        
        app.UseMvc();
    

但是,当我们使用令牌验证自己时,函数的 curl 不会显示 Bearer 令牌。看起来 Swagger 没有将令牌发送到后端。

我们使用 .Net Core 2.1 和 Swagger 2.3。任何帮助将不胜感激,谢谢。

【问题讨论】:

您好,如果有帮助,您能接受我的回答吗? 【参考方案1】:

更新 - Swagger 规范已更改。检查下面@nilay 的答案以获得正确的解决方案。

我也遇到了同样的问题。

两件事是必要的

    你必须像这样输入"bearer &lt;token-here&gt;"。 只放令牌是行不通的。

要让它在 swagger 2.x 中工作,您需要在您的方案定义中附上相应的要求,以表明该方案适用于您 API 中的所有操作:

c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>

     "Bearer", new string[]   
);

完整定义:

services.AddSwaggerGen(c =>
            
                c.SwaggerDoc("v1", new Info  Title = "Some API", Version = "v1" );
                c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
                
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer token\"",
                    Name = "Authorization",
                    In = "header",
                    Type = "apiKey"
                );
                c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
                
                     "Bearer", new string[]   
                );
            );

【讨论】:

如果有人可以添加解释,那将是额外的帮助。 这对我来说似乎很容易解释。通过添加安全要求,您是在告诉 swagger 他应该对所有操作使用 Bearer 方案。他会使用它。 根据 Swagger 规范 swagger.io/specification/#securityRequirementObject,仅定义方案是不够的。您还需要在文档级别或单个操作上提供安全要求对象,以指示该方案适用于哪些操作。 我仍然未经授权。我已将该值添加为第 1 步,但仍然无法访问授权操作。你能帮我提供更多细节吗?使用 .net core 2.1 web api【参考方案2】:

我也面临同样的问题,但我使用的是基于 OpenAPI 的新版本 Swagger。所以,我必须使用下面的 sn-p 来做同样的事情。

var securityScheme = new OpenApiSecurityScheme()

    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer token\"",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
    Scheme = "bearer",
    BearerFormat = "JWT"
;

var securityRequirement = new OpenApiSecurityRequirement

    
            new OpenApiSecurityScheme
            
                Reference = new OpenApiReference
                
                    Type = ReferenceType.SecurityScheme,
                    Id = "bearerAuth"
                
            ,
            new string[] 
    
;

options.AddSecurityDefinition("bearerAuth", securityScheme);
options.AddSecurityRequirement(securityRequirement);

【讨论】:

这是正确的答案。正如一个注释,Scheme 必须是小写的('bearer')。如果您使用 JwtBearerDefaults.AuthenticationScheme(即“Bearer”),它将不起作用。 是的,我遇到过这个问题。 :( 后来才知道 OpenApi 和 Swagger 的 Api 之间也有bearer 的大小写变化。

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

Bearer 用于身份验证令牌,但用于不同的令牌?

从 ASP.NET vNext beta5 移动到 beta7 后 JWT Bearer 令牌身份验证错误

使用 .NET Core 中的公共安全密钥配置 JWT Bearer 令牌验证

Spring 5 LDAP 身份验证和 JWT 令牌作为响应

Bearer Token 认证和 JWT

使用NodeJS验证包含“Bearer:”的JWT标记字符串