Asp.Net Core 正确配置身份认证中间件

Posted

技术标签:

【中文标题】Asp.Net Core 正确配置身份认证中间件【英文标题】:Asp.Net Core configure Identity authentication middleware properly 【发布时间】:2021-07-20 20:18:13 【问题描述】:

要求是我在项目中有 MVC 和 WebAPI。 MVC 视图将在初始时交付 渲染如登录、功能的基本视图(例如:用户/索引、仪表板/索引等)。Web API 将通过 AJAX 和 JWT 用于这些视图中的其他工作。

我正在使用 Asp.Net core Identity 进行在 .Net 5.0 上运行的用户管理相关工作

我对在启动时配置多个身份方案以及在 conigureservices() 和 configure() 中正确配置身份验证/授权管道感到困惑。

    要配置多个身份验证方案,我参考了https://***.com/a/64887479/2058413,因为它是使用我使用的相同版本完成的。所以我的启动方法如下,与该线程中的代码类似。

         public void ConfigureServices(IServiceCollection services)
         
             string connectionString = Configuration.GetConnectionString("default");
             services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
    
             services.AddIdentity<IdentityUser, IdentityRole>()
                 .AddEntityFrameworkStores<AppDBContext>();
    
             services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                 .AddCookie(x =>
                 
                     x.LoginPath = "/Account/Login";
                     x.ExpireTimeSpan = TimeSpan.FromMinutes(10d);
                     x.AccessDeniedPath = "/Account/Register";
                 )
                 .AddJwtBearer(x =>
                 
                     x.RequireHttpsMetadata = false;
                     x.SaveToken = true;
                     x.TokenValidationParameters = new TokenValidationParameters
                     
                         ValidateIssuerSigningKey = true,
                         IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("123456")),
                         ValidateIssuer = false,
                         ValidateAudience = false
                     ;
                 );
    
             services.AddAuthorization(options =>
             
                 var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
                 defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
                 options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
             );
    
    
             services.AddControllersWithViews();
         
    

    我的应用配置方法如下

         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
         
             if (env.IsDevelopment())
             
                 app.UseDeveloperExceptionPage();
             
             else
             
                 app.UseExceptionHandler("/Home/Error");
             
             app.UseStaticFiles();
    
             app.UseRouting();
    
             app.UseAuthentication();
    
             app.UseAuthorization();
    
             app.UseEndpoints(endpoints =>
             
                 endpoints.MapControllerRoute(
                     name: "default",
                     pattern: "controller=Home/action=Index/id?");
             );
         
    

然后控制器中的测试方法(用户应该在认证后被重定向到)如下

    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    public IActionResult Index()
    
        return View();
    

据我了解,管道配置的顺序是正确的。现在这是我面临的问题。

    如 .AddCookie(option=>) 中所指定,用户不会被重定向到登录页面。但是,如果我从 services.AddAuthorization(...) 中删除 JwtBearerDefaults.AuthenticationScheme,它会正确重定向到登录页面。这是为什么呢?

    所以我删除了 JwtBearerDefaults.AuthenticationScheme;这需要我登录,成功登录后我可以看到 HttpContext.User.Identity.IsAuthenticated 设置为 true。但它不会重定向到 Home/Index。没有抛出错误,并且在浏览器控制台 [网络选项卡] 中显示 302 并重定向回登录。由于我已将 [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] 添加到 HomeController 中的 Index 方法,因此我尝试删除该方案并添加 [Authorize] 并再次尝试。它仍然被重定向到登录页面。这是我感到困惑的另一件事。

    所以我删除了与双方案身份验证相关的所有内容,并使用以下代码留下了 ConfigureService()

             string connectionString = Configuration.GetConnectionString("default");
             services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
    
             services.AddIdentity<IdentityUser, IdentityRole>()
                 .AddEntityFrameworkStores<AppDBContext>();
             services.AddControllersWithViews();
    

    现在一切正常(如果未通过身份验证,则重定向到登录,并且在授权后也重定向到 /Home/Index)。

    我也浏览了以下有关多方案身份验证的链接,但我仍然对这种管道配置感到困惑。 ASP.NET Core WebAPI Cookie + JWT Authentication https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2 https://mitchelsellers.com/blog/article/using-multiple-authentication-authorization-providers-in-asp-net-core

    我只需要这个多方案身份验证管道配置部分的帮助。

【问题讨论】:

【参考方案1】:

好的,经过一番研究,主要问题是;

    我在 StartUp (asp.net core 3.x) 中混合了注册服务的旧方法。所以必须清除所有这些。帮助我做到这一点的资源;

Migrate from ASP.NET Core 3.1 to 5.0

ASP.NET Core Middleware

这清理了很多不必要的代码,因为在 .Net 5 中有一些可以使用的快捷方式。

    服务注册的顺序。这可能取决于您使用的服务类型,但在我的情况下,顺序如下所示:
    添加身份 设置 Cookie 和 JWT 身份验证 c) 我的多租户资料 AddCors AddModules(你们中的一些人可以选择。我用它来动态加载插件) 其他东西(但是,即使在这些地方,顺序也可能很重要,具体取决于 你做什么)

另一件事是,我不得不删除 ConfigureApplicationCookie(),因为 AddIdentity 似乎正在这样做。同样在之前的 AddAuthorization() 中,我有代码来指定我想要使用的默认方案(Cookie 和 JWT)。但现在我不得不删除所有这些。原因是 Identity 接管了 cookie 方案,当我在下面指定时,JWTAuth 接管了。

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 

根据您使用的不同服务,通常正确设置启动似乎很棘手。顺序很重要

【讨论】:

以上是关于Asp.Net Core 正确配置身份认证中间件的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.0 身份验证中间件

使用 Google Auth、Angular 4、ASP.Net Core 2 进行身份验证时出现 405

如何从 ASP.NET Core 2.0 中的自定义中间件请求身份验证

asp.net core网关Ocelot的简单介绍& Ocelot集成Identity认证

在 ASP.Net Core 3 中从中间件设置 HTTP 身份验证标头

ASP.NET Core 使用Cookie验证身份