我有一个Web API项目,该项目有许多使用API密钥保护的端点。为了实现这一点,我编写了一些中间件来处理检查API密钥的头并验证它
app.UseMiddleware<ApiKeyMiddleware>();
这非常有效,但我现在需要有一个不需要任何授权的端点,以便在浏览器中查看。我希望这将通过使用AllowAnonymous
属性来完成,但是中间件仍然检查API密钥。
我可以通过移除中间件并将API密钥检查作为属性来实现我想要的,但有更好的方法吗?
编辑:
这是API的关键中间件实现。
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string API_KEY_HEADER = "z-api-key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(API_KEY_HEADER, out var extractedApiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync($"Api Key was not found in request. Please pass key in {API_KEY_HEADEr} header.");
return;
}
var appSettings = context.RequestServices.GetRequiredService<IConfiguration>();
var validApiKey = appSettings.GetValue<string>(API_KEY_HEADER);
if (validApiKey != extractedApiKey)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid api key.");
return;
}
await _next(context);
}
}
您可以使用HttpContext
对象来访问端点和类似元数据的属性。
var endpoint = context.GetEndpoint();
var isAllowAnonymous = endpoint?.Metadata.Any(x => x.GetType() == typeof(AllowAnonymousAttribute));
然后在您的支票中添加一个条件以跳过。
if (isAllowAnonymous == true)
{
await _next(context);
return;
}
注意:您应该将中间件放在Routing
中间件之后,才能使用GetEndpoint
扩展方法。如果您的中间件位于Routing
中间件之前GetEndpoint
扩展方法返回null
app.UseRouting();
app.UseMiddleware<ApiKeyMiddleware>();