Как получить URI в Blazor AuthorizationHandler - PullRequest
1 голос
/ 01 февраля 2020

Я использую собственную политику для защиты страницы в серверном приложении Blazor. Все работает хорошо, за исключением того, что одна из моих политик требует знания параметров запроса. Например, путь URI выглядит примерно так: https://mywebsite/profile/1234, который используется для просмотра / редактирования профиля с id = 1234. Очевидно, что мы хотим, чтобы только пользователь с profileId = 1234 редактировал эту страницу. Как я могу проверить это в моем IAuthorizationHandler?

Я попытался ввести HttpContext и прочитать запрос. Элементы запроса, но это всегда всегда "/" или "/ _blazor", потому что это SPA курс. Я попытался ввести NavigationManager (ранее UriHelper), чтобы получить оттуда URI, но получил ошибку:

'RemoteNavigationManager' has not been initialized.

Я также попытался использовать параметр Resource для передачи информации в мой обработчик. Я не смог найти примеров того, как это сделать, поэтому это моя попытка:

Вот мой код profile.razor, где я ограничиваю доступ с помощью Policy = "CanEditProfile"

@inject NavigationManager  NavigationManager

    <AuthorizeView Policy="CanEditProfile">
        <NotAuthorized>
            <h2 class="mt-5">You are not authorized to view this page</h2>
        </NotAuthorized>
        <Authorized>
            <div class="container my-profile">
                <h2>My Profile</h2>

И мой IAuthorizationHandler код:

        public Task HandleAsync(AuthorizationHandlerContext context)
        {
            if (context == null || httpContextAccessor.HttpContext == null) return Task.CompletedTask;

            // try getting path from httpContext
            var path = httpContextAccessor.HttpContext.Request.Path.Value;
            Console.WriteLine($"Path = {path}");  // this is always "/_blazor"

            // try getting path from resource, passed in from blazor page component
            var resource = context.Resource?.ToString();
            Console.WriteLine($"Resource = {resource}");  // this is always null

            var pendingRequirements = context.PendingRequirements.ToList();

            foreach (var requirement in pendingRequirements)
            {
                if (requirement is EditMemberPermission)
                {
                    // if this user is admin, then grant permission
                    var isAdmin = context.User.IsInRole("Admin");
                    if (isAdmin)
                    {
                        context.Succeed(requirement);
                        continue;
                    }

                    // get requested memberId from uri parameter, e.g. /profile/1234
                    var requestedMemberId = // How do I get this?

                    if (IsOwner(context.User, requestedMemberId))
                    {
                        context.Succeed(requirement);
                    }
                }
            }
            return Task.CompletedTask;
        }

Есть идеи, как этого добиться? Похоже, что это будет распространенный сценарий защиты страницы на основе данных страницы (параметр запроса "id"), к которым пытается получить доступ пользователь. Во многих примерах упоминается защита ресурса и его показ в качестве необязательного параметра, но ни один из примеров, которые я смог найти, не показывает, как на самом деле передается значение и используется его. Как вы можете обезопасить ресурс, если не знаете, что это за ресурс? Я подумал, что может быть способ передать параметр Resource со страницы .razor в обработчик Auth, например так, но я тоже не получил, чтобы это работало.

<AuthorizeView Policy="CanEditProfile" Resource="<pass url somehow?>" />

Заранее спасибо.

1 Ответ

0 голосов
/ 01 февраля 2020

Я получил это с помощью этого кода в моем profile.razor:

@page "/profile/{MemberId}"

<AuthorizeView Policy="CanEditProfile" Resource="@MemberId">

... page content

</AuthorizeView>


@code {
    [Parameter]
    public string MemberId { get; set; }
}

Это получает параметр MemberId из маршрута и передает его в качестве ресурса моему IAuthorizationHandler. В этом методе-обработчике я могу получить его так:

        public Task HandleAsync(AuthorizationHandlerContext context)
        {
            if (context == null) return Task.CompletedTask;

            // get member id from resource, passed in from blazor page component
            var resource = context.Resource?.ToString();
            var hasParsed = int.TryParse(resource, out int requestedMemberId);
            if (hasParsed)
            {
                // compare the requested memberId to the user's actual claim of memberId
                var isAuthorized = requestedMemberId == context.User.GetMemberIdClaim();
                // now we know if the user is authorized or not, and can act accordingly
            }

...