我正在 dotnet 6 中创建一个最小的 API。我有 Swagger/Swashbuckle 的默认实现,一切都很好,直到我添加了一个简单的自定义身份验证中间件(请参阅下面的代码)。
问题是,中间件针对
/swagger/index.html
运行,它在标头中不包含 API 密钥并返回 400 错误(根据下面的第一个 if
语句)。我该如何解决这个问题?
Program.cs
app.UseMiddleware<Auth>();
Auth.cs
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (!context.Request.Headers.ContainsKey("ApiKey"))
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("No ApiKey provided in headers");
}
if (!Guid.TryParse(context.Request.Headers["ApiKey"], out var apiKey))
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("Unable to parse the ApiKey");
}
try
{
/* Look in DB for API Key yada yada yada */
}
catch
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Unauthorized");
}
await next(context);
}
您可以排除不想检查身份验证中间件的路径。
类似这样的事情。
public async Task InvokeAsync(HttpContext context)
{
if(!context.Request.Path.StartsWithSegments("/swagger"))
{
//put your code here for checking API key in header.
}
}
一旦设置响应,您还需要返回,否则您将收到另一个异常。
这是工作代码:
public async Task InvokeAsync(HttpContext context)
{
if(!context.Request.Path.StartsWithSegments("/swagger"))
{
if (!context.Request.Headers.ContainsKey("ApiKey"))
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("No ApiKey provided in headers");
return;
}
if (!Guid.TryParse(context.Request.Headers["ApiKey"], out var apiKey))
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("Unable to parse the ApiKey");
return;
}
try
{
/* Look in DB for API Key yada yada yada */
}
catch
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Unauthorized");
return;
}
}
await this._next(context);
}
}
UseWhen
代替 UseMiddleware
,如下所示:
app.UseWhen(
context => !context.Request.Path.StartsWithSegments("/swagger"),
appBuilder => appBuilder.UseMiddleware<Auth>());
您的
Auth.cs
可以按原样使用。
我目前使用的是dotnet8,但dotnet6应该没有太大区别。