Swagger认证使用JWT Bearer令牌

10
我们正在开发一个带有JWT Bearer认证的.Net Core 2.1 Web API。 应用程序本身将生成并分发令牌,这些令牌将被发送到后端。
虽然我们已经一切就绪,即我们可以从Angular发送Bearer令牌并在Postman中进行测试,但Swagger不会发送Bearer令牌。 我们已经添加了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不会显示承载令牌。似乎Swagger没有将令牌发送到后端。

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


你好,如果我的回答有帮助到您的话,能否接受我的答案呢? - Radim Drtílek
2个回答

19

更新 - Swagger规范已更改,请查看下面@nilay的答案获取正确解决方案。

我曾经遇到过同样的问题。

有两个必要条件:

  1. 你需要像这样放置"bearer <token-here>"。只放置令牌将不起作用。

为了使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[] { } }
                });
            });

如果有人能添加解释,那将是额外的帮助。 - Code Name Jack
对我来说,这似乎很容易理解。通过添加安全要求,您告诉 Swagger 在所有操作中使用 Bearer 方案。他将使用它。 - Radim Drtílek
根据Swagger规范 https://swagger.io/specification/#securityRequirementObject,仅定义方案是不够的。您还需要在文档级别或个别操作上提供安全需求对象,以指示该方案适用于哪些操作。 - Radim Drtílek
我仍然无法获得授权。我已将值添加为第 1 步,但仍无法访问授权操作。您能否帮我提供更多详细信息。 使用 .net core 2.1 web api。 - Prajwal Bhat

6

我也遇到了同样的问题,但我正在使用基于OpenAPI的新版本Swagger。 因此,我必须使用以下代码片段。

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);

2
现在这就是正确的答案。请注意,Scheme必须小写('bearer')。如果您使用JwtBearerDefaults.AuthenticationScheme(即'Bearer'),它将无法工作。 - Jeremy Morren
是的,我曾经遇到过这个问题。:( 然后才知道在OpenApi和Swagger的API之间还有bearer大小写转换的情况。 - Nilay Mehta

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