TGStat
TGStat
Type to search
Advanced channel search
  • flag English
    Site language
    flag Russian flag English flag Uzbek
  • Sign In
  • Catalog
    Channels and groups catalog Regional compilations Thematic compilations Платные каналы Search for channels
    Add a channel/group
  • Ratings
    Rating of channels Rating of groups Posts rating
    Ratings of brands and people
  • Analytics
  • Search by posts
  • Telegram monitoring
  • Promotion
    Advertising through Yandex Business Advertising in channels through TGStat Agency Advertising on TGStat.ru website
async / noway — Будни разработчика

21 May, 21:49

Open in Telegram Share Report

Но вообще, механизм классный, но у него есть один подводный камень, не совсем очевидный, скажем так. И изначально про него и хотел рассказать, но сначала нужно было погрузить в контекст, да и мало ли, кто-то вдруг не знает, что механизм авторизации чуть интереснее чем аттрибуты и мидлвари. Так вот.

Есть метод
Task AuthorizeAsync(
ClaimsPrincipal user,
object? resource,
string policyName);

Мы передаем Пользователя, какой-то ресурс для определения прав и имя политики, чтобы понять что нам вообще нужно проверить. И вот в хэндлере мы делаем такой гибкий механизм
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
AuthorizationRequirement.CanViewVacancyRequirement requirement,
Vacancy resource)
{

if (context.User.IsInRole("Admin") )
{
_logger.LogInformation("User {UserName} has admin role", context.User.Identity.Name);
context.Succeed(requirement);
return Task.CompletedTask;
}

…
If (resource.Initiator?.InitiatorCodeAd == userAdCode)
{
context.Succeed(requirement);
return Task.CompletedTask;
}

_logger.LogInformation("Доступ запрещен: пользователь {UserName} не имеет прав", context.User.Identity?.Name);
return Task.CompletedTask;
}


Вроде все выглядит логично – проверили сначала базовые статичные правила, например клеймы из контектса, потом смотрим на ресурс и поределяем доступ для конкретного пользователя. Логика простая, админа мы всегда пустим, а дальше по обстоятельствам.
Представьте мое лицо, когда меня, как админа, не пустило в систему по запрошенному ресурсу? Я сто раз перепроверил токен, клеймы, правила – все как должно быть, но не пускает. В логах ни ошибки, ни исключения, вообще ничего – просто отказ и все. Знаете в чем дело? Был по ошибке передан не правильный объект, другого типа, а не тот что ожидался. Из-за того, что метод принимает object, то есть вообще все, что угодно, никаких ошибок при билде не было, а то что не удалось объект привести к нашему типу – фреймворк просто отбрасывает такой запрос, не выбрасывает наверх исключение, не логирует попытку, просто отклоняет запрос и все. Но казалось бы, причем тут объект, ведь мы ранее в методе проверяем базовые роли, не обращаемся к объекту, мы заранее можем знать можно ли пропустить пользователя или нет? Но вот в этом и есть особенность данного метода, под капотом сначала собирается контекст, потом передается в связанный хэндлер, а внутри уже хэндлера идет приведение
if (context.Resource is TResource resource)
{
foreach (var req in context.PendingRequirements.OfType())
{
await HandleRequirementAsync(context, req, resource).ConfigureAwait(false);
}
…
}

Тип не подходит, метод отрабатывает впустую, результата нет, нет результата – значит и доступа нет. И поэтому даже не будет проверки ролей, клеймов и т.д., что мы укажем до обращения к ресурсу. Вот так вот бывает.
Ну и что делать с этой информацией? Стараться разделять типы проверок, и те которым конкретный ресурс не нужен, выносить в отдельные хэндлеры. Другой вариант – это написать обертку, и закрыть ее дженериком
public static Task AuthorizeResourceAsync( this IAuthorizationService service, ClaimsPrincipal user, T resource, string policyName) where T : IHasCustomAccess { }

Тогда неподходящий тип не получится передать, ну если только не вызывать напрямую, минуя наше расширение.
async / noway — Будни разработчика
Еще один интересный кейс из рабочей практики. В нашем фреймворке есть мощный механизм для аутентификации и авторизации, можно использовать ролевую модель или более новую на базе клеймов. Есть IAuthorizationService С методом AuthorizeAsync(ClaimsPrincipal, Object, String) Соответственно, мы можем...

169 0 0 6
Catalog
Channels and groups catalog Channels compilations Search for channels Add a channel/group
Ratings
Rating of Telegram channels Rating of Telegram groups Posts rating Ratings of brands and people
API
API statistics Search API of posts API Callback
Our channels
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Read
Академия TGStat Telegram Research 2019 Telegram Research 2021 Telegram Research 2023
Contacts
Справочный центр Support Email Jobs
Miscellaneous
Terms and conditions Privacy policy Public offer
Our bots
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot