Swagger UI 授权不发送令牌

use*_*661 7 swagger swagger-ui asp.net-core swashbuckle.aspnetcore

我是斯瓦格的新手。我正在使用 OpenAPI 3.0.2。

当我运行 Swagger UI 时,顶部和每个 API 都会出现授权按钮,但它们不起作用。当我单击它们时,我可以在 apiKey 框中输入任何文本,它会接受它并表示我已获得授权。但是没有API起作用,它们都返回401

这是Startup.ConfigureServices中的相关代码

services.AddAuthentication(
        x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }
    )
    .AddJwtBearer(
        x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidIssuer = Configuration["Tokens:Issuer"],
                ValidAudience = Configuration["Tokens:Audience"],
            };
        }
    );
services.AddSwaggerGen(
    setupAction =>
    {
        setupAction.SwaggerDoc(
            "LibraryOpenApiSpecification",
            new Microsoft.OpenApi.Models.OpenApiInfo()
            {
                Title = "Library API",
                Version = "2.0",
                Description = "Text",

                Contact = new Microsoft.OpenApi.Models.OpenApiContact()
                {
                    Email = "me@google.com",
                    Name = "user1",
                    Url = new Uri("http://www.google.com")
                }
            }
        );

        setupAction.AddSecurityDefinition(
            "Bearer",
            new OpenApiSecurityScheme
            {
                Name = "Authorization",
                Type = SecuritySchemeType.ApiKey,
                Scheme = "Bearer",
                BearerFormat = "JWT",
                In = ParameterLocation.Header,
                Description = "JWT Authorization header using the Bearer scheme."
            }
        );


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


        var xmlCommentsFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlCommentFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentsFile);
        setupAction.IncludeXmlComments(xmlCommentFullPath);
    }
);
Run Code Online (Sandbox Code Playgroud)

该代码不是我的,是由其他开发人员引入的。如果需要,我将提供更多代码和信息

abd*_*sco 7

这是一个工作示例:

services.AddSwaggerGen(
    c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "ApiPlayground", Version = "v1" });
        c.AddSecurityDefinition(
            "token",
            new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.Http,
                BearerFormat = "JWT",
                Scheme = "Bearer",
                In = ParameterLocation.Header,
                Name = HeaderNames.Authorization
            }
        );
        c.AddSecurityRequirement(
            new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "token"
                        },
                    },
                    Array.Empty<string>()
                }
            }
        );
    }
);
Run Code Online (Sandbox Code Playgroud)

配置完成后,Swagger UI 会为您提供一个进行身份验证的按钮

授权弹出窗口

一旦您填写输入令牌并发送请求,它就会将其发送到Authorization标头内。

要求

现在,应用程序必须为每个请求解析并验证此令牌,因此您必须在Startup.Configure方法内部启用身份验证中间件。

app.UseAuthentication();
app.UseAuthorization();
Run Code Online (Sandbox Code Playgroud)

然后,如果令牌通过验证,您应该能够使用HttpContext.User属性访问用户。

如果您仍然收到 401 错误,这意味着令牌验证存在问题,请检查您是否在Startup.Configure方法中配置了授权服务:

services.AddAuthorization(
    options => options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).Build()
);
Run Code Online (Sandbox Code Playgroud)

[Authorize]这将要求所有请求进行身份验证,除非使用(或) 属性设置另一个授权策略[AllowAnonymous]。这将确保令牌被解析和验证。

这是一个用于签名和验证令牌的端到端 API。

internal class HardCodedConfiguration
{
    public static SymmetricSecurityKey SigningKey = new SymmetricSecurityKey(
        Encoding.UTF8.GetBytes(
            "alongrandomstringhere.11b48736983e87c5cff022c462849ca5b7c5e99b76d81e9707fa35e76024cba8"
        )
    );

    public static SigningCredentials SigningCredentials => new SigningCredentials(
        SigningKey,
        SecurityAlgorithms.HmacSha256
    );
}

[ApiController]
[Route("")]
public class HelloController : ControllerBase
{
    [AllowAnonymous]
    [HttpGet("token")]
    public ActionResult SignToken()
    {
        var token = new JwtSecurityTokenHandler().WriteToken(
            new JwtSecurityToken(
                claims: new List<Claim>()
                {
                    new Claim("name", "abdusco")
                },
                expires:DateTime.Now.AddHours(1),
                signingCredentials: HardCodedConfiguration.SigningCredentials
            )
        );
        return Ok(token);
    }

    [HttpGet]
    public IActionResult AuthorizedEndpoint()
    {
        return Ok(User.Claims.Select(c => new { c.Type, c.Value }).ToList());
    }
}

// inside Startup class
public void ConfigureServices(IServiceCollection services)
{
    // swagger configuration
    // ...
    services.AddControllers();
    services.AddAuthorization(
        options => options.FallbackPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).Build()
    );
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(
            o =>
            {
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = HardCodedConfiguration.SigningKey,
                };
            }
        );
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
Run Code Online (Sandbox Code Playgroud)