令牌身份验证(身份服务器 4)通过中间件来自不同的服务器,但它检查所有不需要授权的端点



我正在使用令牌验证中间件来验证用户,该中间件为此访问了另一台服务器。但问题是,即使不需要,它也会始终检查令牌,即在使用注册 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这样的属性,它将调用特定操作的非授权,并让其余所有操作通过另一个将设置为默认值的属性。