【问题标题】:Token Authentication (Identity Server 4) from different server thru middleware, but it checks for all endpoints which doesn't needed to be authorized通过中间件来自不同服务器的令牌身份验证(身份服务器 4),但它检查所有不需要授权的端点
【发布时间】:2020-05-10 11:35:02
【问题描述】:

我正在使用令牌验证中间件对用户进行身份验证,为此它会访问另一台服务器。但问题是,即使不需要,它也会始终检查令牌,即在使用注册 API 或任何其他不需要任何验证的时候。

这是我的 TokenValidationMiddleware.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]”,但为此我必须修改后端和前端中的所有端点。这也不是一个好方法。

请为此提出解决方案。

提前致谢。

【问题讨论】:

    标签: c# asp.net-core-webapi identityserver4 access-token asp.net-core-middleware


    【解决方案1】:

    您可以在中间件中对照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);
    }
    

    您还可以检查相反的情况:针对 IAllowAnonymous,如果端点具有 [AllowAnonymous] 属性。

    if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
    

    附言

    您可以查看 ASP.NET Core Authorization MiddleWare source code 以获得灵感。

    【讨论】:

    • 我无法理解你的代码中的context.GetEndpoint();是什么,如果是ControllerContext则始终为null,如果是HttpContext则不包含此函数。跨度>
    • @PriyankPahuja 我的错误。应该是httpContext.GetEndpoint(),更新了答案
    • 此方法适用于asp.net core 3.0及以上,但我需要2.2的解决方案。我不想更新它。
    • 这只是扩展方法。在 2.2 中,您应该可以使用:var endpoint = httpContext.Features.Get&lt;IEndpointFeature&gt;()?.Endpoint; 而不是 GetEndpoint。
    【解决方案2】:

    中间件就像 .net 处理程序。当您不需要控制器特定数据时使用它们:asp.net core middleware vs filters

    另一方面,您可以像这样使用自定义策略提供程序:https://docs.microsoft.com/en-us/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-3.1

    使用外部服务提供政策评估。

    使用大量策略(例如,针对不同的房间号或年龄),因此使用 AuthorizationOptions.AddPolicy 调用添加每个单独的授权策略是没有意义的。

    在运行时根据外部数据源(如数据库)中的信息创建策略或通过另一种机制动态确定授权要求。

    因此,您可以使用像BypassAuth 这样的属性,它将为特定操作调用非授权,而让所有其余部分通过另一个将设置为默认值的属性。

    【讨论】:

      猜你喜欢
      • 2015-10-19
      • 1970-01-01
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      • 2012-06-05
      相关资源
      最近更新 更多