Asp.Net Boilerplate .Net Core 2.0 AbpAuthorizationFilter - вызов вызов / несанкционированный - PullRequest
0 голосов
/ 25 июня 2018

Я использую Asp.Net Core 2.0 с Asp.Net Boilerplate версии 3.4.0 веб-приложением.

Когда у меня есть аутентифицированный пользователь, у которого нет необходимых разрешений для доступа к ресурсу, ChallengeResult устанавливается AbpAuthorizationFilter через Abp framework. Это приводит к тому, что пользователь возвращается на страницу входа по умолчанию. Если пользователь аутентифицирован, я хотел бы установить ForbidResult и перенаправить его на страницу AccessDenied по умолчанию.

Просмотрев мои параметры, я вижу, что у меня есть следующие параметры:

  1. Добавьте мой собственный фильтр авторизации и зарегистрируйтесь в MvcOptions до конфигурации службы AddAbp(). Фильтр условно установит результат на Challenge или Forbid
  2. Переопределить событие OnRedirectToLogin (т.е. настроить для аутентифицированных пользователей)
  3. Переопределить обработчик HandleChallengeAsync (т. Е. Проверить, аутентифицирован ли запрос и выполнить ForbidResult или ChallengeResult для неаутентифицированных запросов)

Я заметил в .NET Framework версии ABP, что в AbpMvcAuthorizeFilter есть перезаписываемые методы (т.е. HandleUnauthorizedRequest); однако это не относится к версии .Net Core. Смотрите GitHub Issue 1256 -> Сделать AbpMvcAuthorizeFilter и AbpApiAuthorizeFilter перезаписываемыми

Вопрос:

Кому-нибудь еще нужно изменить стандартное Abp поведение возврата ChallengeResult для неавторизованных запросов? Если да, какое решение вы использовали? Я что-то упустил в конфигурации Abp или Asp.Net Core (кроме трех опций, перечисленных выше), которые позволили бы мне лучше контролировать это поведение?

Если я выберу обходной путь, это будет похоже на хак, чтобы контролировать это поведение.

Вариант 1:

Из трех перечисленных опций вариант one представляется наиболее чистым и подходящим местом для обработки этой логики. Это тоже не красиво, так как я скопировал бы весь AbpAuthorizationFilter, чтобы изменить только несколько строк кода.

Текущий код:

context.Result = new ChallengeResult();

Предлагаемое изменение:

if (context.HttpContext.User.Identity.IsAuthenticated)
{
    //User is already logged in.. No need to redirect to the 
    //login page
    context.Result = new ForbidResult();
}
else
{
    context.Result = new ChallengeResult();
}

Полный код ниже:

AbpAuthorizationFilter.cs См. Строки блока захвата - 58 - 77

Вариант 2:

Второй вариант выглядит как kludgy , потому что логика, которую я хотел бы ввести в событие OnRedirectToLogin, должна была бы исходить из предположения, что аутентифицированный пользователь попытался получить доступ к неавторизованному ресурсу. В настоящее время я вижу только то, как Events.RedirectToLogin поднимается в CookieAuthenticationHandler методом HandleChallengeAsync. С учетом вышесказанного можно предположить, что это событие будет вызвано только результатом ChallengeResult. CookieAuthenticationHandler.cs

Вариант 3:

Третий вариант будет последним (то есть избегать любой ценой)

Основная цель

Основная цель - предоставить пользователям, прошедшим аутентификацию, доступ к несанкционированным ресурсам. Вместо того, чтобы перенаправлять пользователя на страницу входа, его следует перенаправить на неавторизованную / запрещенную страницу, которая четко указывает на то, что он не авторизован. Это может включать возможность предложить пользователю предоставить более высокие привилегированные учетные данные. При запросе пользователя он пахнет потоком результатов ChallengeResult, поэтому, возможно, я просто ответил на свой вопрос. При текущем поведении у меня не так много контекстной информации о «почему» было выдано ChallengeResult. Я буду знать, что пользователь вошел в систему и что событие OnRedirectToLogin было инициировано. Этого, вероятно, достаточно, чтобы настроить поведение ChallengeResult для аутентифицированных пользователей. Это начинает чувствовать, что это правильное решение. Любые предложения или отзывы об использовании этого подхода?

1 Ответ

0 голосов
/ 28 июня 2018

Из трех вариантов я выбрал второй вариант (переопределить событие OnRedirectToLogin) по следующим причинам:

  1. Введен минимальный код без дублирования всего фильтра авторизации, чтобы изменить только двастроки кода.
  2. Больше контроля над процессом вызова (приложение MVC также является клиентом OIDC) с собственным набором ролей и разрешений (см. Решение кода ниже)
  3. Во время этого ответаСобытие OnRedirectToLogin вызывается только HandleChallengeAsync в CookieAuthenticationHandler , поэтому это похоже на правильное место для переопределения поведения ChallengeResult.

Решение:

options.Events.OnRedirectToLogin = context =>
{
    if (context.HttpContext?.User?.Identity?.IsAuthenticated == false)
    {
        //The user is not authenticated... Use the "oidc" challenge scheme 
        //and send them to identity server.
        var task = context.HttpContext.ChallengeAsync("oidc");
        task.WaitAndUnwrapException();

        return Task.CompletedTask;
    }

    var accessDeniedPath = BuildRedirectUri(context.HttpContext, options.AccessDeniedPath);

    context.Response.Redirect(accessDeniedPath);
    context.Response.StatusCode = 302;

    return Task.CompletedTask;
};

Примечание:

Следует отметить, что поведение по умолчанию AbpAuthorizationFilter не отражает поведение акций Asp.Net.Core MVC 2.0 AuthorizeFilter.При сбое авторизации для аутентифицированного пользователя Asp.Net Core MVC 2.0 AuthorizeFilter возвращает результат Forbid.

По умолчанию Asp.Net Core MVC AuthorizeFilter делегирует авторизацию IPolicyEvaluator.Если авторизация завершается неудачно, и пользователь проходит проверку подлинности, устанавливается результат Forbid или, если авторизация завершается неудачно, а пользователь не прошел проверку подлинности, устанавливается результат Challenge.

PolicyEvaluator.cs

var result = await _authorization.AuthorizeAsync(context.User, resource, policy);
if (result.Succeeded) 
{ 
    return PolicyAuthorizationResult.Success(); 
} 

// If authentication was successful, return forbidden, otherwise challenge 
return (authenticationResult.Succeeded)  
    ? PolicyAuthorizationResult.Forbid()  
    : PolicyAuthorizationResult.Challenge(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...