Не было указано authenticationScheme, и не было найдено DefaultForbidScheme с авторизацией на основе настраиваемой политики

У меня есть обработчик авторизации на основе настраиваемой политики, как определено ниже. Аутентификация выполняется до того, как пользователь попадет в это приложение, поэтому мне нужна только авторизация. Я получаю сообщение об ошибке:

No authenticationScheme was specified, and there was no DefaultForbidScheme.

Если проверка авторизации прошла успешно, я не получаю сообщение об ошибке и все в порядке. Эта ошибка возникает только в случае сбоя проверки авторизации. Я ожидал, что 401 вернется в случае неудачи.

public class EasRequirement : IAuthorizationRequirement
{
    public EasRequirement(string easBaseAddress, string applicationName, bool bypassAuthorization)
    {
        _client = GetConfiguredClient(easBaseAddress);
        _applicationName = applicationName;
        _bypassAuthorization = bypassAuthorization;
    }

    public async Task<bool> IsAuthorized(ActionContext actionContext)
    {
        ...
    }
}
public class EasHandler : AuthorizationHandler<EasRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EasRequirement requirement)
    {
        var mvcContext = context.Resource as ActionContext;

        bool isAuthorized;

        try
        {
            isAuthorized = requirement.IsAuthorized(mvcContext).Result;
        }
        catch (Exception)
        {
            // TODO: log the error?
            isAuthorized = false;
        }

        if (isAuthorized)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        context.Fail();
        return Task.FromResult(0);
    }
}
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var easBaseAddress = Configuration.GetSection("EasBaseAddress").Value;
        var applicationName = Configuration.GetSection("ApplicationName").Value;
        var bypassAuthorization = bool.Parse(Configuration.GetSection("BypassEasAuthorization").Value);

        var policy = new AuthorizationPolicyBuilder()
            .AddRequirements(new EasRequirement(easBaseAddress, applicationName, bypassAuthorization))
            .Build();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("EAS", policy);
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddSingleton<IAuthorizationHandler, EasHandler>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();

        app.UseMvc();
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
16
0
12 214
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Авторизация и проверка подлинности тесно связаны в ASP.NET Core. Если авторизация не удалась, это будет передано обработчику аутентификации для обработки ошибки авторизации.

Таким образом, даже если вам не нужна фактическая аутентификация для идентификации пользователей, вам все равно потребуется настроить некоторую схему аутентификации, которая способна обрабатывать запрещенные и оспаривать результаты (403 и 401).

Для этого вам нужно вызвать в AddAuthentication() и настроить схему запрета / вызова по умолчанию:

services.AddAuthentication(options =>
{
    options.DefaultChallengeScheme = "scheme name";

    // you can also skip this to make the challenge scheme handle the forbid as well
    options.DefaultForbidScheme = "scheme name";

    // of course you also need to register that scheme, e.g. using
    options.AddScheme<MySchemeHandler>("scheme name", "scheme display name");
});

MySchemeHandler должен реализовывать IAuthenticationHandler, и в вашем случае вам особенно необходимо реализовать ChallengeAsync и ForbidAsync:

public class MySchemeHandler : IAuthenticationHandler
{
    private HttpContext _context;

    public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        _context = context;
        return Task.CompletedTask;
    }

    public Task<AuthenticateResult> AuthenticateAsync()
        => Task.FromResult(AuthenticateResult.NoResult());

    public Task ChallengeAsync(AuthenticationProperties properties)
    {
        // do something
    }

    public Task ForbidAsync(AuthenticationProperties properties)
    {
        // do something
    }
}

Есть ли способ предотвратить описанное вами поведение по умолчанию? «Если авторизация не удалась, это будет передано обработчику аутентификации для обработки ошибки авторизации»

Christoph Adamakis 09.10.2018 15:20

@ChristophAdamakis Нет, так связаны аутентификация и авторизация. В случае сбоя авторизации схема проверки подлинности должна обработать этот сбой. - Что бы вы хотели там делать вместо этого? Что-то должно произойти.

poke 09.10.2018 15:57

@ajamrozek Запрос учетных данных, как во всплывающем окне браузера, которое запрашивает ваш логин? Или просто перенаправление на какую-то форму входа? Первое невозможно, а второе явно предотвращается вашей собственной схемой аутентификации. Может быть, вам стоит задать новый вопрос, касающийся того, что именно вы делаете. Не стесняйтесь размещать ссылку на вопрос здесь, и я посмотрю.

poke 16.04.2019 11:40

«Не должно быть». Вызов принят;) Оказывается, у меня были некоторые устаревшие вещи, которые включали WindowsAuth в launchsettings.json. Вынул это, и больше нет подсказки. В остальном этот ответ действительно помог мне.

ajamrozek 16.04.2019 16:33

@ajamrozek Windows auth там имеет смысл - рад, что вы в этом разобрались :)

poke 16.04.2019 18:51

А если кому интересно, как должно выглядеть «сделать что-нибудь», обратитесь к stackoverflow.com/a/54587054/106688

Andrey 10.10.2019 17:40

Для IIS / IIS Express можно просто добавить эту строку вместо всего вышеперечисленного в принятый ответ, чтобы получить соответствующий ожидаемый ответ 403;

 services.AddAuthentication(IISDefaults.AuthenticationScheme);

Другие вопросы по теме