如何正确地从AuthorizationHandler返回404以防止信息泄露

时间:2019-07-10 02:39:12

标签: c# asp.net-core

我正在编写一个授权处理程序,以删除控制器中的许多样板代码。

我想确保自己正确执行此操作,因为在实际失败时按要求调用“成功”似乎有点奇怪。注意//-> see explanation above!

下面的代码中的行

重要的是,如果您无权访问ABN,而您无法对具有访问权限但没有所需权限的ABN进行操作,则不要泄露系统中存储的ABN级别。

我为需求找到的所有示例似乎都认为您可以执行或不能执行某些操作。

这个问题是关于我想使用的状态码,但是我不确定如何使用AspnetCore正确实现 Prevent Information Disclosure Http Status Codes

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Linq;
using System.Threading.Tasks;
using WebApi.Common.Authorisation;

namespace WebApi.App.Requirements
{
    /// <summary>
    /// Handles the authorisation of the Current user attempting to access an ABN.
    /// If the user has an assocation with an ABN, but they cant perform the operation on it, then return 403 no
    /// If the user has no association with the ABN, then we don't want to disclose that the other ABN exists within the system at all so 404, 
    /// </summary>
    public class TaxEntityHandler : AuthorizationHandler<TaxEntity>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TaxEntity requirement)
        {
            var userIdentifier = context.User.Claims.FirstOrDefault(x => x.Type == ApiClaims.ContactClaimType);
            if (userIdentifier == null)
            {
                context.Fail();
            }
            else
            {
                var authorizationFilterContext = context.Resource as AuthorizationFilterContext;

                if (authorizationFilterContext.RouteData.Values.TryGetValue("abn", out var abnValue))
                {
                    var abn = (string)abnValue;

                    var accessLevel = AccessHelper.DetermineAccess(context.User, abn);
                    if (accessLevel == EntityAccessLevel.None)
                    {
//-> see explanation above!
                        authorizationFilterContext.Result = new NotFoundResult();
                        context.Succeed(requirement);
                    }
                    else
                    {
                        if ((accessLevel & requirement.Level) == accessLevel)
                        {
                            context.Succeed(requirement);
                        }
                        else
                        {
                            context.Fail();
                        }
                    }
                }
            }

            return Task.CompletedTask;
        }
    }
}

上面的完整实现有效,但看起来很奇怪。

我也对此块进行了试验,但是由于httpresponse对象上的IsStarted,导致整个堆栈都被触发了异常,但实际上它还返回了404。如果我未对响应写任何内容,则仍然是403已交付。

if (accessLevel == EntityAccessLevel.None)
{
    authorizationFilterContext.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
    using(var sw = new StreamWriter(authorizationFilterContext.HttpContext.Response.Body))
    {
        sw.Write(NoData);
    }
    context.Fail();
}

最后,如果我只是设置状态码而使上下文失败,那么将交付403。

if (accessLevel == EntityAccessLevel.None)
{
    authorizationFilterContext.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
    context.Fail();
}

如果有更好的例子,我想知道

0 个答案:

没有答案