@apoltavcevА у вас есть планы довести до ума фичу с сокрытием авторов? Я рад не видеть когтеточки за миллионы денег в своей ленте, но из "Читают сейчас" посты не скрываются, и всё равно можно случайно вляпаться :(
Верно - потому что пропускать или запрещать запросы - это ответственность авторизации, отдельного шага после аутентификации.
Грубо говоря, аутентификация проверяет у пользователя документы, это может быть паспорт или водительские права, а авторизация решает, какие именно документы (уже проверенные к этому моменту) принимать - любые или, например, только паспорт.
Тут есть странное (с моей точки зрения) поведение.
Допустим, у вас метод аутентификации по умолчанию - Jwt. Если мы не меняли политику авторизации по умолчанию, она равна
new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()
У политик авторизации есть свойство AuthenticationSchemes, которое определяет, какие обработчики аутентификации будут запущены. По умолчанию оно пустое. Это значит, что политика будет вызывать обработчик аутентификации по умолчанию, т.е. Jwt.
Неочевидно, что [Authorize(AuthenticationSchemes)] определяет методы аутентификации в дополнение политике по умолчанию.
И вот что получается с разными вариантами:
[Authorize]
[] + [] = [] -> политика авторизации использует метод аутентификации по умолчанию - Jwt.
[Authorize(AuthenticationSchemes = "ApiKey")]
[] + ["ApiKey"] = ["ApiKey"] -> только метод ApiKey - потому что AuthenticationSchemes политики больше не пустое, поэтому метод Jwt не используется.
А вот что происходит, если в политике авторизации указать методы аутентификации:
builder.Services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder("Jwt")
.RequireAuthenticatedUser()
.Build();
});
[Authorize]
["Jwt"] + [] = ["Jwt"] -> метод Jwt
[Authorize(AuthenticationSchemes = "ApiKey")]
["Jwt"] + ["ApiKey"] = ["Jwt", "ApiKey"] -> методы Jwt или ApiKey.
Хм, да, вы правы. Если в [Authorize] не указывать Policy, берётся политика по умолчанию, а мы в ней уже разрешили оба метода аутентификации.
Но тогда получается всё ещё проще: политику авторизации по умолчанию мы не трогаем (или по крайней мере не указываем методы аутентификации):
builder.Services.AddAuthorization();
и перечисляем требуемые методы в [Authorize]:
// Метод аутентификации по умолчанию
[Authorize]
// Только ApiKey
[Authorize(AuthenticationSchemes = "ApiKey")]
// ApiKey или Bearer
[Authorize(AuthenticationSchemes = "ApiKey,Bearer")]
Мне кажется, ваше решение сильно переусложнено. И есть несколько ошибок.
Давайте сначала разберём ApiKeyAuthenticationHandler из первой части:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!TryGetApiKey(out var apiKey, out var failureMessage))
{
return AuthenticateResult.Fail(failureMessage!);
}
Когда схеме аутентификации недостаточно данных (например, заголовок с API-ключом отсутствует вообще), она должна возвращать AuthenticationResult.NoResult(). Это нужно чтобы не заваливать аутентификацию целиком, а дать другим схемам возможность тоже отработать. О, это же как раз наш случай!
AuthenticationResult.Fail(...) - это для случаев, когда схема уже однозначно определена, например, если в запросе передан нужный заголовок, но в нём нет ключа или он невалидный:
ApiKeyAuthenticationHandler.cs
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Context.Request.Headers.TryGetValue("X-API-Key", out var apiKeyHeaderValue))
{
return Task.FromResult(AuthenticateResult.NoResult());
}
// Проверяем ключ...
if (apiKeyHeaderValue != "14f259ea-1b55-4135-a335-b4d3d6a1030f")
{
return Task.FromResult(AuthenticateResult.Fail("Invalid API key"));
}
var principal = new ClaimsPrincipal(new ClaimsIdentity([/* claims go here... */], "ApiKey"));
return Task.FromResult(AuthenticateResult.Success(new(principal, "ApiKey")));
}
Теперь посмотрим на CompositeAuthenticationHandler. Он не нужен :) Нужно настроить политику авторизации:
Тогда сначала произойдёт попытка аутентифицироваться по ключу, а если не получилось, то по токену. Конечно же, атрибут [Authorize(AuthenticationSchemes = ...)] с указанием конкретных схем продолжит работать.
Мне кажется, вы неправильно поняли фичу? lock никуда не девается, плюшки появляются из-за использования System.Threading.Lock вместо object, а не потому что мы lock вручную переписываем на using, в доке есть пример (подозрительно похожий на ваш ;)
помогает слегка другая последовательность действий:
отключить БП -> закрыть крышку -> убрать в рюкзак.
На LTT было видео про это. Ноуты часто оказываются достаточно тупы и в режиме modern sleep не "видят", когда питание переключается и когда надо бы умерить аппетит. Т.е. в каком состоянии вы закрыли крышку (от сети / от батареи), в том ноут и остаётся, пока крышку не откроете.
За старание замазать имя - 5. За реализацию - 2 :)
@apoltavcevА у вас есть планы довести до ума фичу с сокрытием авторов? Я рад не видеть когтеточки за миллионы денег в своей ленте, но из "Читают сейчас" посты не скрываются, и всё равно можно случайно вляпаться :(
Если нужен цифровой блок, удобнее всего его докупить отдельным девайсом, мне кажется.
А что, Nvidia не при чём?
Нужно отдать Nvidia должное - это столько людей им удаётся одурачивать.
Так вы сравните, например, с Thermalright Peerless Assassin, а не Noctua.
Верно - потому что пропускать или запрещать запросы - это ответственность авторизации, отдельного шага после аутентификации.
Грубо говоря, аутентификация проверяет у пользователя документы, это может быть паспорт или водительские права, а авторизация решает, какие именно документы (уже проверенные к этому моменту) принимать - любые или, например, только паспорт.
Тут есть странное (с моей точки зрения) поведение.
Допустим, у вас метод аутентификации по умолчанию - Jwt. Если мы не меняли политику авторизации по умолчанию, она равна
У политик авторизации есть свойство
AuthenticationSchemes
, которое определяет, какие обработчики аутентификации будут запущены. По умолчанию оно пустое. Это значит, что политика будет вызывать обработчик аутентификации по умолчанию, т.е. Jwt.Неочевидно, что
[Authorize(AuthenticationSchemes)]
определяет методы аутентификации в дополнение политике по умолчанию.И вот что получается с разными вариантами:
[]
+[]
=[]
-> политика авторизации использует метод аутентификации по умолчанию - Jwt.[]
+["ApiKey"]
=["ApiKey"]
-> только метод ApiKey - потому чтоAuthenticationSchemes
политики больше не пустое, поэтому метод Jwt не используется.А вот что происходит, если в политике авторизации указать методы аутентификации:
["Jwt"]
+[]
=["Jwt"]
-> метод Jwt["Jwt"]
+["ApiKey"]
=["Jwt", "ApiKey"]
-> методы Jwt или ApiKey.Хм, да, вы правы. Если в
[Authorize]
не указыватьPolicy
, берётся политика по умолчанию, а мы в ней уже разрешили оба метода аутентификации.Но тогда получается всё ещё проще: политику авторизации по умолчанию мы не трогаем (или по крайней мере не указываем методы аутентификации):
и перечисляем требуемые методы в
[Authorize]
:Мне кажется, ваше решение сильно переусложнено. И есть несколько ошибок.
Давайте сначала разберём
ApiKeyAuthenticationHandler
из первой части:Когда схеме аутентификации недостаточно данных (например, заголовок с API-ключом отсутствует вообще), она должна возвращать
AuthenticationResult.NoResult()
. Это нужно чтобы не заваливать аутентификацию целиком, а дать другим схемам возможность тоже отработать. О, это же как раз наш случай!AuthenticationResult.Fail(...)
- это для случаев, когда схема уже однозначно определена, например, если в запросе передан нужный заголовок, но в нём нет ключа или он невалидный:ApiKeyAuthenticationHandler.cs
Теперь посмотрим на
CompositeAuthenticationHandler
. Он не нужен :) Нужно настроить политику авторизации:Тогда сначала произойдёт попытка аутентифицироваться по ключу, а если не получилось, то по токену. Конечно же, атрибут
[Authorize(AuthenticationSchemes = ...)]
с указанием конкретных схем продолжит работать.Удалить нельзя, но в следующий раз можно заменить текст комментария на "del" или точку. Обычно к этому относятся с пониманием.
Это получился
continue
, но неbreak
.Ещё были неплохи советские Цивилизация и Команда Икс: Защита от НЛО :)
А если серьёзно, Космические рейнджеры действительно были топ. До сих пор иногда слушаю оттуда музыку.
Телефон просто блокируется, не становится кирпичом и не взрывается. Его можно разблокировать и продолжить свои дела.
Не буду спорить со сложностью эмбеда (не моя стихия), но кажется, что автор и сам туда не лезет с сырыми языками, а просто пишет на Rust UEFI-аппку.
Так а в чём проблема написать прошивку на языке, который позволяет писать прошивки?
Мне кажется, вы неправильно поняли фичу? lock никуда не девается, плюшки появляются из-за использования System.Threading.Lock вместо object, а не потому что мы lock вручную переписываем на using, в доке есть пример (подозрительно похожий на ваш ;)
Спасибо. Оказывается, у нас внутри компании было объявление, но достаточно незаметное, и я пропустил.
Это вам нужно обратиться к вашим мэйнтайнерам архитектуры x86, у вас же есть такие? Это ведь общепринятая практика в разработке проектов. /s
С некоторыми моделями ноутов вместо
закрыть крышку -> отключить БП -> убрать в рюкзак
помогает слегка другая последовательность действий:
отключить БП -> закрыть крышку -> убрать в рюкзак.
На LTT было видео про это. Ноуты часто оказываются достаточно тупы и в режиме modern sleep не "видят", когда питание переключается и когда надо бы умерить аппетит. Т.е. в каком состоянии вы закрыли крышку (от сети / от батареи), в том ноут и остаётся, пока крышку не откроете.