ASP.NET Core - Identity 身份框架配置
在本章中,我们将安装和配置 Identity 身份框架,这只需要一点工作。 如果您转到 Visual Studio 并创建一个新的 ASP.NET Core 应用程序,并选择将身份验证设置为单个用户帐户的完整 Web 应用程序模板,则该新项目将包括为您设置的 Identity 身份框架的所有部分。
我们从一个空项目开始。 我们现在将从头开始设置 Identity 身份框架,这是了解完整应用程序模板中所有部分的好方法,因为如果您没有详细了解所有代码,可能会感到困惑。
开始之前,我们需要安装依赖项,即 Microsoft.AspNet.Identity。我们将继续安装 Microsoft.AspNet.Identity.EntityFramework ,然后实施与实体框架配合使用的身份框架。
如果我们依赖 Identity.EntityFramework,则该包包含 Identity 包。
如果您构建自己的数据存储,则可以只使用 Identity 包。
安装依赖项后,我们可以创建一个客户用户类,其中包含我们要存储的有关用户的所有信息。
对于此应用程序,我们将从身份框架提供的类继承,该类将为我们提供所有必需品,如用户名属性和存储散列密码的位置。
我们还需要修改我们的 FirstAppDemoDbContext 类以继承身份框架的 IdentityDb 类。
IdentityDb 为我们提供了使用 Entity 实体框架存储为用户信息所需的一切。 一旦我们设置了 User 类和 DBContext,我们就需要使用 Startup 类的 ConfigureServices 方法将身份服务配置到应用程序中。
就像我们需要添加服务来支持 MVC 框架一样,Identity 框架也需要将服务添加到应用程序才能工作。
这些服务包括像 UserStore 服务和 SignInManager 这样的服务。
我们会将这些服务注入到我们的控制器中,以在适当的时候创建用户并发布 cookie。
最后,在启动的 Configure 方法中,我们需要添加 Identity 中间件。
此中间件不仅有助于将 cookie 转换为用户身份,而且还可以确保用户不会看到带有 401 响应的空白页面。
现在让我们按照下面给出的步骤操作。
步骤 1 − 我们需要继续添加对 Identity 框架的依赖。 让我们将 Microsoft.AspNet.Identity.EntityFramework 依赖项添加到 project.json 文件中。 这将包括我们需要的所有其他必要的 Identity 包。
{ "version": "1.0.0-*", "compilationOptions": { "emitEntryPoint": true }, "dependencies": { "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", "EntityFramework.Commands": "7.0.0-rc1-final", "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final", "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final" }, "commands": { "web": "Microsoft.AspNet.Server.Kestrel", "ef": "EntityFramework.Commands" }, "frameworks": { "dnx451": { }, "dnxcore50": { } }, "exclude": [ "wwwroot", "node_modules" ], "publishExclude": [ "**.user", "**.vspscc" ] }
步骤 2 − 保存此文件。 Visual Studio 恢复包,现在我们可以添加我们的用户类。 让我们通过右键单击 Models 文件夹并选择 Add → Class 来添加 User 类。
如上图所示,调用此类 User 并单击"Add"添加按钮。 在此类中,您可以添加属性来保存要存储的有关用户的任何信息。
步骤 3 − 让我们从 Identity 框架提供的类派生 User 类。 它是 Identity.EntityFramework 命名空间中的 IdentityUser 类。
using Microsoft.AspNet.Identity.EntityFramework; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace FirstAppDemo.Models { public class User : IdentityUser { } }
步骤 4− 现在让我们转到 IdentityUser,将光标放在该符号上,然后按 F12 以查看 Visual Studio 的元数据视图。
#region Assembly Microsoft.AspNet.Identity.EntityFramework, Version = 3.0.0.0, namespace Microsoft.AspNet.Identity.EntityFramework { public class IdentityUser : IdentityUser<string> { public IdentityUser(); public IdentityUser(string userName); } }
步骤 5 − 可以看到IdentityUser是从字符串的IdentityUser派生出来的。 您可以通过从 IdentityUser 派生并指定我们的通用类型参数来更改主键的类型。 您还可以使用主键存储内容,主键最好是整数值。
步骤 6 − 现在让我们将光标放在字符串的 IdentityUser 上,然后再次按 F12 转到元数据视图。
您现在可以默认查看与用户相关的所有信息。 信息包括以下内容 −
我们不会在此应用程序中使用但可用的字段。
Identity 框架可以跟踪特定用户的登录尝试失败次数,并可以在一段时间内锁定该帐户。
用于存储 PasswordHash、PhoneNumber 的字段。 我们将使用的两个重要字段是 PasswordHash 和 UserName。
我们还将隐式使用用户的主键和 ID 属性。 如果您需要查询特定用户,也可以使用该属性。
步骤 7 − 现在,我们需要确保 User 包含在我们的 DBContext 中。 因此,让我们打开应用程序中的 FirstAppDemoDBContext,而不是直接从 DBContext 派生它,它是内置的实体框架基类,我们现在需要从 身份数据库上下文。
using Microsoft.AspNet.Identity.EntityFramework; using Microsoft.Data.Entity; namespace FirstAppDemo.Models { public class FirstAppDemoDbContext : IdentityDbContext<User> { public DbSet<Employee> Employees { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Data Source = (localdb)\\MSSQLLocalDB; Initial Catalog = FirstAppDemo;Integrated Security = True; Connect Timeout = 30;Encrypt = False;TrustServerCertificate = True; ApplicationIntent = ReadWrite;MultiSubnetFailover = False"); } } }
步骤 8 − IdentityDbContext 类也在 Microsoft.AspNet.Identity.EntityFramework 命名空间中,我们可以指定它应该存储的用户类型。 这样,我们添加到 User 类的任何其他字段都会进入数据库。
IdentityDbContext 带来了额外的 DbSet,不仅用于存储用户,还用于存储有关用户角色和用户声明的信息。
我们的 User 类现在已经准备好了。 我们的 FirstAppDemoDbContext 类配置为使用身份框架。
我们现在可以进入 Configure 和 ConfigureServices 来设置身份框架。
步骤 9 − 现在让我们从 ConfigureServices 开始。 除了我们的 MVC 服务和我们的实体框架服务,我们还需要添加我们的身份服务。 这将添加Identity 身份框架完成其工作所依赖的所有服务。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddEntityFramework() .AddSqlServer() .AddDbContext<FirstAppDemoDbContext> (option => option.UseSqlServer(Configuration["database:connection"])); services.AddIdentity<User, IdentityRole>() .AddEntityFrameworkStores<FirstAppDemoDbContext>(); }
AddIdentity 方法采用两个通用类型参数——用户实体的类型和角色实体的类型。
这两个泛型类型参数是我们用户的类型——我们刚刚创建的用户类和我们想要使用的角色类。 我们现在将使用内置的 IdentityRole。 此类位于 EntityFramework 命名空间中。
当我们使用带有标识的实体框架时,我们还需要调用第二个方法 − AddEntityFrameworkStores。
AddEntityFrameworkStores 方法将配置 UserStore 等服务,该服务用于创建用户并验证其密码。
步骤 10 − 以下两行是我们为应用程序配置服务所需的全部内容。
services.AddIdentity<User, IdentityRole>() .AddEntityFrameworkStores<FirstAppDemoDbContext>();
步骤 11 − 我们还需要添加中间件。 我们插入中间件的位置很重要,因为如果我们在管道中插入中间件的时间太晚,它将永远没有机会处理请求。
如果我们需要在 MVC 控制器内部进行授权检查,我们需要在 MVC 框架之前插入身份中间件,以确保成功处理 cookie 和 401 错误。
public void Configure(IApplicationBuilder app) { app.UseIISPlatformHandler(); app.UseDeveloperExceptionPage(); app.UseRuntimeInfoPage(); app.UseFileServer(); app.UseIdentity(); app.UseMvc(ConfigureRoute); app.Run(async (context) => { var msg = Configuration["message"]; await context.Response.WriteAsync(msg); }); }
步骤 12 − 我们插入中间件的位置就是我们将添加身份中间件的位置。 以下是 Startup.cs 文件的完整实现。
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using FirstAppDemo.Services; using Microsoft.AspNet.Routing; using System; using FirstAppDemo.Entities; using Microsoft.Data.Entity; using FirstAppDemo.Models; using Microsoft.AspNet.Identity.EntityFramework; namespace FirstAppDemo { public class Startup { public Startup() { var builder = new ConfigurationBuilder() .AddJsonFile("AppSettings.json"); Configuration = builder.Build(); } public IConfiguration Configuration { get; set; } // This method gets called by the runtime. // Use this method to add services to the container. // For more information on how to configure your application, // visit http://go.microsoft.com/fwlink/?LinkID = 398940 public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddEntityFramework() .AddSqlServer() .AddDbContext<FirstAppDemoDbContext>(option => option.UseSqlServer(Configuration["database:connection"])); services.AddIdentity<User, IdentityRole>() .AddEntityFrameworkStores<FirstAppDemoDbContext>(); } // This method gets called by the runtime. // Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { app.UseIISPlatformHandler(); app.UseDeveloperExceptionPage(); app.UseRuntimeInfoPage(); app.UseFileServer(); app.UseIdentity(); app.UseMvc(ConfigureRoute); app.Run(async (context) => { var msg = Configuration["message"]; await context.Response.WriteAsync(msg); }); } private void ConfigureRoute(IRouteBuilder routeBuilder) { //Home/Index routeBuilder.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}"); } // Entry point for the application. public static void Main(string[] args) => WebApplication.Run<Startup>(args); } }
步骤 13 − 现在让我们继续构建应用程序。 在下一章中,我们需要添加另一个 Entity 实体框架迁移以确保我们的 SQL Server 数据库中有 Identity 模式。