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 изображения, которые я прикрепил ниже для получения дополнительной информации:
Мой вопрос: можем ли мы сделать 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 должен знать список маршрутов.