All streams
Search
Write a publication
Pull to refresh
10
0.1
Send message

Достаточно. dotnet restore отдельным шагом - это просто небольшая оптимизация сборки контейнера, смысл которой в том, что зависимости у вас скорее всего меняются реже, чем код, поэтому их можно закешировать в отдельном слое.

Причём у автора это реализовано неправильно, потому что он перед рестором копирует все файлы (обратите внимание на COPY . .), инвалидируя этим самым кеш с зависимостями. Лучше обратиться к доке Microsoft.

В рамках борьбы с оплавлениями 12VHPWR был разработан новый стандарт подключения 12V-2x6, который был призван решить проблему с перегревами.

12V-2x6 - это всё тот же плавящийся 12VHPWR... с силовыми пинами длиннее на 0.25мм. "Разработан новый стандарт", ага.

Самописное работает только в режиме test-signed code, который никто ради вашего драйвера включать не будет.

Для этого есть Z-Wave :) Но девайсы, конечно, дороже, чем ZigBee, иногда значительно.

За старание замазать имя - 5. За реализацию - 2 :)

@apoltavcevА у вас есть планы довести до ума фичу с сокрытием авторов? Я рад не видеть когтеточки за миллионы денег в своей ленте, но из "Читают сейчас" посты не скрываются, и всё равно можно случайно вляпаться :(

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

Нужно отдать Nvidia должное - это столько людей им удаётся одурачивать.

Так вы сравните, например, с Thermalright Peerless Assassin, а не Noctua.

Верно - потому что пропускать или запрещать запросы - это ответственность авторизации, отдельного шага после аутентификации.

Грубо говоря, аутентификация проверяет у пользователя документы, это может быть паспорт или водительские права, а авторизация решает, какие именно документы (уже проверенные к этому моменту) принимать - любые или, например, только паспорт.

Тут есть странное (с моей точки зрения) поведение.

Допустим, у вас метод аутентификации по умолчанию - 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. Он не нужен :) Нужно настроить политику авторизации:

builder.Services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder("ApiKey", "Bearer")
        .RequireAuthenticatedUser()
        .Build();
});

Тогда сначала произойдёт попытка аутентифицироваться по ключу, а если не получилось, то по токену. Конечно же, атрибут [Authorize(AuthenticationSchemes = ...)] с указанием конкретных схем продолжит работать.

Удалить нельзя, но в следующий раз можно заменить текст комментария на "del" или точку. Обычно к этому относятся с пониманием.

Это получился continue, но не break.

Для меня российские оригинальные игры это Герои меча и магии,

Ещё были неплохи советские Цивилизация и Команда Икс: Защита от НЛО :)

А если серьёзно, Космические рейнджеры действительно были топ. До сих пор иногда слушаю оттуда музыку.

Телефон просто блокируется, не становится кирпичом и не взрывается. Его можно разблокировать и продолжить свои дела.

Не буду спорить со сложностью эмбеда (не моя стихия), но кажется, что автор и сам туда не лезет с сырыми языками, а просто пишет на Rust UEFI-аппку.

Information

Rating
3,537-th
Registered
Activity