Swagger UI授权未发送令牌

fdbelqdn  于 9个月前  发布在  其他
关注(0)|答案(3)|浏览(95)

我是斯威格的新人我使用的是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 = "[email protected]",
                    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);
    }
);

代码不是我的,是另一个开发人员带来的。我会提供更多的代码和信息,如果需要的话

q43xntqr

q43xntqr1#

下面是一个工作示例:

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

一旦你配置了它,Swagger UI就会给你一个按钮来进行身份验证

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

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

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

然后,如果令牌通过验证,您应该能够访问具有HttpContext.User属性的用户。
如果您仍然收到401错误,这意味着令牌验证有问题,请检查您是否在Startup.Configure方法中配置了授权服务:

services.AddAuthorization(
    options => options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).Build()
);

这将要求所有请求进行身份验证,除非另一个授权策略设置了[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(); });
}
wydwbb8l

wydwbb8l2#

为了让Swagger UI(.NET 6,OpenApi v3,Swashbuckle v6.5)认证为我工作,我必须创建一个AuthenticationRequirementsOperationFilter并将其添加到这个github回答中提到的过滤器中。同样重要的是,关键字bearerAddSecurityDefinitionOpenApiSecurityScheme中保持相同。
下面是示例代码:
Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(opt =>
        {
            opt.SwaggerDoc("v1", new OpenApiInfo { Title = "My Api", Version = "v1" });
            opt.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.Http,
                BearerFormat = "JWT",
                In = ParameterLocation.Header,
                Scheme = "bearer"
            });
            opt.OperationFilter<AuthenticationRequirementsOperationFilter>();
        });
    }
}

public class AuthenticationRequirementsOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation.Security == null)
            operation.Security = new List<OpenApiSecurityRequirement>();

        var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
        operation.Security.Add(new OpenApiSecurityRequirement
        {
            [scheme] = new List<string>()
        });
    }
}
7hiiyaii

7hiiyaii3#

如果你想使用Type = SecuritySchemeType.ApiKey,那么你需要在关键字Bearer后面加上token,比如'Bearer ',并且token变量的名称应该是Authorization only,或者你可以用Http替换Security Scheme Type,那么你不需要声明任何变量名称,也不需要在传递token时附加bearer。

相关问题