我正在使用令牌验证中间件来验证用户,该中间件为此访问了另一台服务器。但问题是,即使不需要,它也会始终检查令牌,即在使用注册 API 或任何其他不需要任何验证时。
这是我的令牌验证中间件.cs文件。
public async Task Invoke(HttpContext httpContext, UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
// **>>>>>BELOW CHECK IS MANUAL, WHICH IS ALSO NOT CORRECT.<<<<<**
if (!httpContext.Request.Path.StartsWithSegments("/api/Authentication/Login") && !httpContext.Request.Path.StartsWithSegments("/api/Authentication/Refresh"))
{
var headerKeys = httpContext.Request.Headers.Keys;
// **issue comes here**
// **it always discard the request which does not have any token.**
if (headerKeys.Contains("Authorization"))
{
// validation code, which hits another server.
}
else
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized Access");
return;
}
}
await _next.Invoke(httpContext);
}
此中间件始终检查引发的每个请求的令牌验证。
我想为匿名请求或控制器或特定端点上方没有任何 [Authorize] 属性的请求绕过此中间件。
一种解决方案是将所有匿名端点存储在某个地方,并对中间件进行检查,这根本不正确。
另一种是将所有安全端点的路由修改为"api/secure/[controller]",但为此我必须修改后端和前端中的所有端点。这也不是一个好方法。
请为此提出解决方案。
提前谢谢。
您可以根据中间件中的IAuthorizeData
检查端点:
public async Task Invoke(HttpContext httpContext, UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
// Check if endpoint has any authorize data, like [Authorize] attribute
var endpoint = httpContext.GetEndpoint();
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>();
if (authorizeData != null && authorizeData.Any())
{
// If you need to depend on particular scheme ("Bearer" in my example):
var scheme = authorizeData[0].AuthenticationSchemes;
if (scheme == JwtBearerDefaults.AuthenticationScheme)
{
// Code only for "Bearer" auth scheme
}
var headerKeys = httpContext.Request.Headers.Keys;
// **issue comes here**
// **it always discard the request which does not have any token.**
if (headerKeys.Contains("Authorization"))
{
// validation code, which hits another server.
}
else
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized Access");
return;
}
}
await _next.Invoke(httpContext);
}
你也可以检查相反的情况:如果端点有[AllowAnonymous]
属性,则针对IAllowAnonymous
。
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
附言
您可以查看 ASP.NET 核心授权中间件源代码以获取灵感。
中间件就像.net处理程序。当您不需要控制器特定数据时,可以使用它们:asp.net 核心中间件与过滤器
另一方面,您可以使用如下自定义策略提供程序:https://learn.microsoft.com/en-us/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-3.1
使用外部服务提供策略评估。
使用大量策略(例如,针对不同的房间号或年龄(,因此使用 AuthorizationOptions.AddPolicy 调用添加每个单独的授权策略是没有意义的。
在运行时根据外部数据源(如数据库(中的信息创建策略,或通过其他机制动态确定授权要求。
因此,您可以使用像BypassAuth
这样的属性,它将调用特定操作的非授权,并让其余所有操作通过另一个将设置为默认值的属性。