ASP.NET Identity框架2.0的自定义主键类型

在处理大量数据的应用中,使用字符串作为用户ID可能会导致检索信息时的性能问题。因此,将主键类型更改为整数是一个更好的解决方案。ASP.NET Identity框架2.0引入了一些新特性,其中包括通用的主键类型,使得可以自定义主键类型。Identity框架2.0包含在Visual Studio 2013更新2中(2014年5月12日发布)。

本文将通过以下步骤展示如何将主键数据类型从字符串更改为整数:

创建MVC项目

使用Visual Studio 2013更新2创建一个新的ASP.NET Web应用程序,命名为Identity2IntPK,并选择MVC模板和Individual User Account选项。Visual Studio 2013的MVC模板会创建如下结构:

  • IdentityConfig文件包含一个ApplicationUserManager类,可以在这里设置密码强度。
  • Startup.Auth包含一个Startup类的子类,可以在这里设置第三方登录提供者,如Facebook、Google等。
  • IdentityModels包含ApplicationUser和ApplicationDbContext。将主要更改这个文件。
  • AccountViewModels包含一些用于数据传输和验证的类。
  • AccountController包含AccountController类,负责登录、注册、密码重置等。
  • Account文件夹包含一些视图文件,如Login.cshtml、Register.cshtml、ResetPassword.cshtml。

创建并修改Identity类

需要修改以下文件以完成此任务:

  • IdentityModels.cs
  • IdentityConfig.cs
  • Startup.Auth.cs

1. IdentityModels.cs:

打开文件并添加UserRoleIntPk、UserClaimIntPk、UserLoginIntPk、RoleIntPk、UserStoreIntPk、RoleStoreIntPk类。

public class UserRoleIntPk : IdentityUserRole<int> { } public class UserClaimIntPk : IdentityUserClaim<int> { } public class UserLoginIntPk : IdentityUserLogin<int> { } public class RoleIntPk : IdentityRole<int, UserRoleIntPk> { public RoleIntPk() { } public RoleIntPk(string name) { Name = name; } } public class UserStoreIntPk : UserStore<ApplicationUser, RoleIntPk, int, UserLoginIntPk, UserRoleIntPk, UserClaimIntPk> { public UserStoreIntPk(ApplicationDbContext context) : base(context) { } } public class RoleStoreIntPk : RoleStore<RoleIntPk, int, UserRoleIntPk> { public RoleStoreIntPk(ApplicationDbContext context) : base(context) { } }

同时更改ApplicationUser和ApplicationDbContext类。

public class ApplicationUser : IdentityUser<int, UserLoginIntPk, UserRoleIntPk, UserClaimIntPk> { public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager) { var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); // 添加自定义用户声明 return userIdentity; } } public class ApplicationDbContext : IdentityDbContext<ApplicationUser, RoleIntPk, int, UserLoginIntPk, UserRoleIntPk, UserClaimIntPk> { public ApplicationDbContext() : base("DefaultConnection") { } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } }

2. IdentityConfig.cs:

打开App_Start文件夹中的此文件并更改ApplicationUserManager类。更改后的ApplicationUserManager将如下所示:

public class ApplicationUserManager : UserManager<ApplicationUser, int> { public ApplicationUserManager(IUserStore<ApplicationUser, int> store) : base(store) { } public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) { var manager = new ApplicationUserManager(new UserStoreIntPk(context.Get<ApplicationDbContext>())); // 配置用户名验证逻辑 manager.UserValidator = new UserValidator<ApplicationUser, int>(manager) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; // 配置密码验证逻辑 manager.PasswordValidator = new PasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = true, RequireDigit = true, RequireLowercase = true, RequireUppercase = true, }; manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser, int> { MessageFormat = "Your security code is: {0}" }); manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser, int> { Subject = "Security Code", BodyFormat = "Your security code is: {0}" }); manager.EmailService = new EmailService(); manager.SmsService = new SmsService(); var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, int>(dataProtectionProvider.Create("ASP.NET Identity")); } return manager; } }

3. Startup.Auth.cs:

打开App_Start文件夹中的此文件并用新代码替换旧代码。

// 旧代码 OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) // 新代码 OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>( validateInterval: TimeSpan.FromMinutes(30), regenerateCallback: (manager, user) => user.GenerateUserIdentityAsync(manager), getUserIdCallback: (id) => (Int32.Parse(id.GetUserId())) )

更改AccountController以使用新的主键

工作几乎完成了。如果编译代码,会得到大约16个错误,所有错误都在AccountController.cs文件中。因此,需要更改此文件以适应新系统。

打开AccountController.cs文件,并将所有userId类型从字符串更改为整数。然后替换所有User.Identity.GetUserId()为int.Parse(User.Identity.GetUserId()),除了LinkLogin函数。

同时,将LinkLoginCallback更改为:

// GET: /Account/LinkLoginCallback public async Task LinkLoginCallback() { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); if (loginInfo == null) { return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); } IdentityResult result = await UserManager.AddLoginAsync(int.Parse(User.Identity.GetUserId()), loginInfo.Login); if (result.Succeeded) { return RedirectToAction("Manage"); } return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); }

运行应用程序

现在编译项目,如果一切顺利,然后运行它。点击导航菜单中的注册并添加一个用户。

Entity Framework将为创建一个数据库,包含AspNet授权表。如果想检查数据库中发生了什么,那么打开服务器资源管理器中的DefaultConnection。右键单击AspNetUsers表并选择打开表定义,将看到ID现在是整数而不是字符串。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485