自定义 ASP.NET 核心 Cookie 身份验证

Custom ASP.NET Core Cookie Authentication

过去几天我一直在研究 ASP.NET Core 中的服务身份验证。我的应用程序有一个简单的身份验证令牌系统。预计请求上有一个 cookie,我获取该 cookie 并向我的身份验证服务器发出请求。授权服务器还给我用户的权利。如果 cookie 不存在,或者授权请求返回失败,应用程序应该返回 401。如果成功,它将转到管道的下一部分并检查权利的授权。

我按照预期设置了我的身份验证中间件 - 继承自 AuthenticationHandler、AuthenticationMiddleware 等。我的自定义身份验证处理程序继承自 Authenticationhandler 并覆盖了 HandleAuthenticateAsync()。此方法使用用户提供的 cookie 获取用户数据,创建我的 ClaimsPrincipal,以及 returns AuthenticateResult.Success 或 AuthenticateResult.Fail.

当 AuthenticationResult.Fail returns 时,我认为该应用程序会退出,但我的应用程序仍会转到管道的下一部分 (app.UseMvc()),当我认为它会 return 401 错误。

我的 Startup.cs 如下所示。

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication();
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseCustomAuthentication(new CustomAuthenticationOptions()
        {
            AutomaticChallenge = true,
            AutomaticAuthenticate = true
        });

        app.UseMvc();
    }
}

这将导致身份验证失败,我会在输出中看到它,但 UseMvc 仍将 运行。直到我对服务执行此操作它才会退出,但出现授权错误而不是应该标记的身份验证错误。

        services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                             .RequireAuthenticatedUser()
                             .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
        });

这是应该设置的方式吗?身份验证失败时,管道不应该关闭吗?

When authentication fails, shouldn't the pipeline shut down?

假设您有另一个身份验证中间件:

    app.UseCustomAuthentication(new CustomAuthenticationOptions()
    {
        AutomaticChallenge = true,
        AutomaticAuthenticate = true
    });
    app.UseOtherAuthentication(new OtherAuthenticationOptions()
    {
        AutomaticChallenge = true,
        AutomaticAuthenticate = true
    });

如果管道在第一次身份验证失败时结束,其他身份验证中间件永远不会运行。它的可扩展性会降低。

还有一点,假设您想允许使用 AllowAnonymous 属性对匿名请求执行某些操作。你怎么允许?

即使身份验证中间件失败,不调用 HttpContext.Authentication.ChallengeAsync() 或使用 Authorize 属性,服务器也不会响应 401、403 或 302。

据我所知,这是预期的行为,内置 cookie 身份验证的行为相同。如果你想首先强制认证用户,你需要全局添加它(就像你做的那样)或在控制器顶部使用 Authorize 属性。