Как правильно вернуть 404 от AuthorizationHandler, чтобы предотвратить раскрытие информации - PullRequest
0 голосов
/ 10 июля 2019

Я пишу обработчик авторизации для удаления большого количества стандартного кода из контроллеров.

Я хочу убедиться, что я делаю это правильно, так как кажется немного странным вызывать "Succeed" натребование, когда оно на самом деле терпит неудачу.Обратите внимание на строку в коде ниже //-> see explanation above!

Важно, чтобы мы не раскрывали ABN, хранящиеся в нашей Системе, если у вас нет доступа к ABN, тогда как вы не можете выполнять операции с ABN, которыеу вас есть доступ, но у вас нет требуемого уровня разрешений.

Все примеры, которые я нашел для требований, похоже, предполагают, что вы можете или не можете выполнить какое-либо действие.

Этот вопрос говорит о кодах состояния, которые я хочу использовать, но я просто не уверен, как правильно реализовать с помощью AspnetCore Предотвратить раскрытие информации Http Коды состояния

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;
        }
    }
}

Полная реализация, описанная выше, работает, но кажется странной.

Я также экспериментировал с этим блоком, но это привело к тому, что исключения запускались по всему стеку из-за IsStarted для объекта httpresponse, но он также фактически возвращал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();
}

Если есть лучший пример для этого, я бы хотел знать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...