Не была определена схема authenticationScheme, и не было найдено DefaultForbidScheme с авторизацией на основе пользовательских политик - PullRequest
0 голосов
/ 02 июля 2018

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

Не указана схема аутентификации, и не существует 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();
    }
}

1 Ответ

0 голосов
/ 02 июля 2018

Авторизация и аутентификация тесно связаны в 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;

    Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        _context = context;
    }

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

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

    Task ForbidAsync(AuthenticationProperties properties);
    {
        // do something
    }
}
...