Условная аутентификация Windows на AspNetCore2 с HTTP.SYS

Я использую AspNetCore 2 с HTTP.SYS. Я пытаюсь реализовать схему аутентификации, которая

      1. Performs custom (stateless) authentication if a request has a given header, or
2. If not, defaults back to windows auth

Моей первоначальной попыткой было добавить схему политики, которая выбирает соответствующую схему проверки подлинности на основе запроса. Однако это не совсем работает - похоже, что аутентификация Http.sys выполняется ДО того, как мой селектор политики даже вызывается (см. комментарий во фрагменте кода).

В отчаянной и невежественной попытке я возился с установкой AllowAnonymous в true, но это, похоже, приводит к тому, что аутентификация Windows никогда не используется.

Есть ли способ правильно выбрать схему аутентификации?

      var host = new WebHostBuilder()
    .ConfigureServices(services =>
    {
        services
            .AddAuthentication("DynamicAuthenticationScheme")
            .AddScheme<AuthenticationSchemeOptions, CustomAuth>("Custom", _ => { })
            .AddPolicyScheme("DynamicAuthenticationScheme", "Default system policy", cfgOptions =>
            {
                cfgOptions.ForwardDefaultSelector = ctx =>
                {
                    // Auth looks to be done beforehand already; if setting a breakpoint here, ctx.User is already given
                    if (ctx.Request.Headers.ContainsKey("CUSTOM-AUTH"))
                        return "Custom";

                    return HttpSysDefaults.AuthenticationScheme;
                };
            });
    })
    .UseHttpSys(options =>
    {
        options.Authentication.Schemes = AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
        options.Authentication.AllowAnonymous = false;
    })
    .UseUrls("http://localhost:7200")
    .Configure(app =>
    {
        app.UseAuthentication();
        app.Map(new PathString("/test"), cfg =>
            cfg.Use(async (context, next) =>
            {
                await context.Response.WriteAsync($"Hello {context.User.Identity?.Name}");
            }));
    })
    .Build();


await host.StartAsync();

1 ответ

Я «решил» это сейчас, добавив пользовательское промежуточное программное обеспечение:

      class MyMiddleware : IMiddleware
{
  public async Task InvokeAsync(HttpContext context, RequestDelegate next)
  {
     if(ShouldUseCustomAuth(context))
     {
        var authResult = await context.AuthenticateAsync("Custom");
        if(authResult.Succeeded)
        {
           context.User = auth.Principal;
           await next(context);
           return;
        }
     }

     await context.ChallengeAsync("Windows");
  }
}

Я оставлю вопрос открытым на мгновение, хотя у кого-то есть более приятное решение (может быть, в конце концов, с использованием политик?)

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