gpt4 book ai didi

c# - 带有 api key 身份验证的 Swagger 客户端生成

转载 作者:行者123 更新时间:2023-12-05 07:42:51 28 4
gpt4 key购买 nike

我有一个现有的 C# ASP.NET Web API 2 项目 (.NET 4.6.1),我需要在其中集成 Swagger 以生成文档以及客户端 SDK(目前只有 C#)。这是使用最新版本 (5.5.3) 中的 Swashbuckle 完成的。

除了一件事,一切都很顺利。我遇到的问题是我的 SwaggerConfig.cs 中定义的安全性(通过 HTTP header 的 apiKey)最终出现在输出 JSON 中,但不知何故它没有链接到任何方法(即使它是强制性的)。

我的安全配置定义如下:

GlobalConfiguration.Configuration.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "Dummy API")
c.ApiKey("apiKey")
.Description("API Key Authentication")
.Name("X-API-Key")
.In("header");
}).EnableSwaggerUi(c =>
{
c.EnableApiKeySupport("X-API-Key", "header");
});

以及生成的 Swagger JSON 中的结果:

"securityDefinitions": {
"apiKey": {
"type": "apiKey",
"description": "API Key Authentication",
"name": "X-API-Key",
"in": "header"
}
}

这是我得到的:

"/api/ping": {
"get": {
"tags": [
"Dummy"
],
"summary": "Ping.",
"operationId": "ping",
"consumes": [],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
}
}
}
}

与我想要获得的相比:

"/api/ping": {
"get": {
"tags": [
"Dummy"
],
"summary": "Ping.",
"operationId": "ping",
"consumes": [],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
}
},
"security": [
{
"apiKey": []
}
]
}
}

知道我应该在项目中更改什么以便生成 security 部分吗?

最佳答案

这个问题和其他问题对我一路走来帮助很大。在我的例子中,我总是只遗漏了一件事——当用 [Authorize] 装饰 Action / Controller 时,SwaggerUI 没有将我选择的 header 名称/值 (X-API-KEY) 传递给我的身份验证处理程序。 .我的项目使用 .NET Core 3.1 和 Swashbuckle 5。我创建了一个继承 IOperationFilter 的自定义类使用 Swashbuckle.AspNetCore.Filters下面的 nuget 包搭载了它们对 oauth2 的实现。

// Startup.cs
// ...
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = nameof(BoardMinutes), Version = "v1" });

// Adds authentication to the generated json which is also picked up by swagger.
options.AddSecurityDefinition(ApiKeyAuthenticationOptions.DefaultScheme, new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Name = ApiKeyAuthenticationHandler.ApiKeyHeaderName,
Type = SecuritySchemeType.ApiKey
});

options.OperationFilter<ApiKeyOperationFilter>();
});

关键组件是 options.AddSecurityDefinition() (我有一些开放端点,不想提供全局过滤器)以及 options.OperationFilter<ApiKeyOperationFilter>() .

// ApiKeyOperationFilter.cs
// ...
internal class ApiKeyOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
// Piggy back off of SecurityRequirementsOperationFilter from Swashbuckle.AspNetCore.Filters which has oauth2 as the default security scheme.
var filter = new SecurityRequirementsOperationFilter(securitySchemaName: ApiKeyAuthenticationOptions.DefaultScheme);
filter.Apply(operation, context);
}
}

最后 - 完整的图片是身份验证处理程序和身份验证选项

// ApiKeyAuthenticationOptions.cs
// ...
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultScheme = "API Key";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
}

// ApiKeyAuthenticationHandler.cs
// ...
internal class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
private const string ProblemDetailsContentType = "application/problem+json";
public const string ApiKeyHeaderName = "X-Api-Key";

private readonly IApiKeyService _apiKeyService;
private readonly ProblemDetailsFactory _problemDetailsFactory;

public ApiKeyAuthenticationHandler(
IOptionsMonitor<ApiKeyAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
IApiKeyService apiKeyService,
ProblemDetailsFactory problemDetailsFactory) : base(options, logger, encoder, clock)
{
_apiKeyService = apiKeyService ?? throw new ArgumentNullException(nameof(apiKeyService));
_problemDetailsFactory = problemDetailsFactory ?? throw new ArgumentNullException(nameof(problemDetailsFactory));
}

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKeyHeaderValues))
{
return AuthenticateResult.NoResult();
}

Guid.TryParse(apiKeyHeaderValues.FirstOrDefault(), out var apiKey);

if (apiKeyHeaderValues.Count == 0 || apiKey == Guid.Empty)
{
return AuthenticateResult.NoResult();
}

var existingApiKey = await _apiKeyService.FindApiKeyAsync(apiKey);

if (existingApiKey == null)
{
return AuthenticateResult.Fail("Invalid API Key provided.");
}

var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, existingApiKey.Owner)
};

var identity = new ClaimsIdentity(claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
var ticket = new AuthenticationTicket(principal, Options.Scheme);

return AuthenticateResult.Success(ticket);
}

protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.StatusCode = StatusCodes.Status401Unauthorized;
Response.ContentType = ProblemDetailsContentType;
var problemDetails = _problemDetailsFactory.CreateProblemDetails(Request.HttpContext, StatusCodes.Status401Unauthorized, nameof(HttpStatusCode.Unauthorized),
detail: "Bad API key.");

await Response.WriteAsync(JsonSerializer.Serialize(problemDetails));
}

protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
{
Response.StatusCode = StatusCodes.Status403Forbidden;
Response.ContentType = ProblemDetailsContentType;
var problemDetails = _problemDetailsFactory.CreateProblemDetails(Request.HttpContext, StatusCodes.Status403Forbidden, nameof(HttpStatusCode.Forbidden),
detail: "This API Key cannot access this resource.");

await Response.WriteAsync(JsonSerializer.Serialize(problemDetails));
}
}

关于c# - 带有 api key 身份验证的 Swagger 客户端生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44161390/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com