AuthorizationHandler<T> не запускается в методе контроллера AllowAnonymous

Я делаю приложение, используя.Net Core 2.1 и AngularJS. В моем приложении.Net Core есть несколько методов, которые разрешают доступ как аутентифицированным, так и не прошедшим проверку пользователям.

Это мой метод получения личного профиля

    /// <summary>
    ///     Find personal profile.
    /// </summary>
    /// <param name="id">Id of user. 0 for the request sender profile</param>
    /// <returns></returns>
    [HttpGet("personal-profile/{id}")]
    [AllowAnonymous]
    public async Task<IActionResult> FindProfile([FromRoute] int? id)
    {
        // Get requester identity.
        var profile = IdentityService.GetProfile(HttpContext);

        // Search for accounts.
        var accounts = UnitOfWork.Accounts.Search();

        if (id == null || id < 1)
        {
            if (profile != null)
                accounts = accounts.Where(x => x.Id == profile.Id);
            else
                return Ok();
        }
        else
            accounts = accounts.Where(x => x.Id == id);

        // Only search for active account.
        accounts = accounts.Where(x => x.Status == AccountStatus.Available);

        // Find the first account in system.
        var account = await accounts.FirstOrDefaultAsync();
        return Ok(account);
    }

Это мой класс AuthorizationHandler.

    /// <summary>
    ///     Handle requirement asychronously.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="requirement"></param>
    /// <returns></returns>
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
        SolidAccountRequirement requirement)
    {
        // Convert authorization filter context into authorization filter context.
        var authorizationFilterContext = (AuthorizationFilterContext) context.Resource;

        //var httpContext = authorizationFilterContext.HttpContext;
        var httpContext = _httpContextAccessor.HttpContext;

        // Find claim identity attached to principal.
        var claimIdentity = (ClaimsIdentity) httpContext.User.Identity;

        // Find email from claims list.
        var email =
            claimIdentity.Claims.Where(x => x.Type.Equals(ClaimTypes.Email))
                .Select(x => x.Value)
                .FirstOrDefault();

        // Email is invalid.
        if (string.IsNullOrEmpty(email))
        {
            context.Fail();
            return;
        }

        // Find accounts based on conditions.
        var accounts = _unitOfWork.Accounts.Search();
        accounts = accounts.Where(x =>
            x.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase) && x.Status == AccountStatus.Available);

        // Find the first matched account in the system.
        var account = await accounts.FirstOrDefaultAsync();

        // Account is not found.
        if (account == null)
            return;

        // Initiate claim identity with newer information from database.
        var claimsIdentity = new ClaimsIdentity();
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, account.Nickname));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, Enum.GetName(typeof(AccountRole), account.Role)));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Authentication,
            Enum.GetName(typeof(AccountStatus), account.Status)));

        // Update claim identity.
        _identityService.SetProfile(httpContext, account);
        context.Succeed(requirement);
    }

Это то, что я делаю.

  • В AuthorizationHandlerпроверить личность запроса (проанализировано промежуточным ПО JWT Bearer)
  • Запросите базу данных, чтобы найти информацию о пользователе.
  • Когда пользователь найден, информация о пользователе будет прикреплена к httpContext.Items[ClaimTypes.Actor]

Вот что происходит в моем коде: - Используйте почтальона, чтобы отправить запрос api/user/personal-profile/0 для получения запроса профиля отправителя. - В FindProfile, profile переменная равна нулю вместо информации пользователя, что означает AuthorizationHandler не срабатывает.

Если я удалю [AllowAnonymous] атрибут из FindProfile метод, все работает отлично.

Пожалуйста, смотрите эти 2 изображения, которые я прикрепил ниже для получения дополнительной информации:

С AllowAnonymous

Без Разрешить Аноним

Мой вопрос: можем ли мы сделать AuthorizationHandler быть запущенным методом AllowAnonymous. В моей системе есть несколько API, которые могут использовать оба вида этих пользователей.

  • Если пользователь является администратором, некоторая дополнительная информация будет возвращена.
  • Если пользователь обычный пользователь, будет возвращено мало информации.

Спасибо

1 ответ

Решение

> Can we make AuthorizationHandler be triggered with AllowAnonymous method?

Нет, ты не можешь. [AllowAnonymous] Обходит все утверждения авторизации. Если вы заинтересованы, это соответствующий код в AuthorizeFilter.OnAuthorizationAsync реализация.

if (context.Filters.Any(item => item is IAllowAnonymousFilter))
{
   return;
}

Подумай об удалении AllowAnonymous и добавив немного пользовательской логики. Например, вы можете создать собственный фильтр MVC. Скажем так:

public class MyAllowAnonymous : ActionFilterAttribute {}

Затем в AuthorizationHandler проверяет, authorizationFilterContext.Filters Коллекция имеет этот фильтр. Если да, возвращает context.Succeed(requirement);,

  • рассмотреть возможность создания отдельной реализации AuthorizationHandler с другим IAuthorizationRequirement,

  • вместо проверки фильтров вы можете напрямую получить название маршрута по authorizationFilterContext.ActionDescriptor и решить, разрешен ли анонимный доступ. Но тогда ваш AuthorizationHandler должен знать список маршрутов.