【问题标题】:Change User Id type to int in ASP.NET Identity in VS2015在 VS2015 的 ASP.NET 身份中将用户 ID 类型更改为 int
【发布时间】:2015-12-29 06:47:14
【问题描述】:

默认情况下,VS 2015 中的 ASP.NET Identity 使用字符串作为 AspNet*** 表的主键。我想改用 int 类型的 id。经过一些研究,结果发现框架开箱即用地支持不同类型的 id。在下面的答案中,我将展示为实现这一目标需要做出哪些改变。

更新:添加我的答案后,我在 asp.net 网站上发现了这篇博文,描述相同但更全面:http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-identity


    【解决方案1】:
    1. IdentityModels.cs改成这个:

      // New derived classes
      public class UserRole : IdentityUserRole<int>
      {
      }
      
      public class UserClaim : IdentityUserClaim<int>
      {
      }
      
      public class UserLogin : IdentityUserLogin<int>
      {
      }
      
      public class Role : IdentityRole<int, UserRole>
      {
          public Role() { }
          public Role(string name) { Name = name; }
      }
      
      public class UserStore : UserStore<ApplicationUser, Role, int,
          UserLogin, UserRole, UserClaim>
      {
          public UserStore(ApplicationDbContext context): base(context)
          {
          }
      }
      
      public class RoleStore : RoleStore<Role, int, UserRole>
      {
          public RoleStore(ApplicationDbContext context): base(context)
          {
          }
      }
      
      // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
      public class ApplicationUser : IdentityUser<int, UserLogin, UserRole, UserClaim>
      {
          public DateTime? ActiveUntil;
      
          public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
          {
              // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
              var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
              // Add custom user claims here
              return userIdentity;
          }
      }
      
      public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, int,
          UserLogin, UserRole, UserClaim>
      {
          public ApplicationDbContext()
              : base("DefaultConnection")
          {
          }
      
          public static ApplicationDbContext Create()
          {
              return new ApplicationDbContext();
          }
      }
      
    2. 在 `App_Start\IdentityConfig.cs 中,更改以下类:

      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 UserStore(context.Get<ApplicationDbContext>()));
              // Configure validation logic for usernames
              manager.UserValidator = new UserValidator<ApplicationUser, int>(manager)
              {
                  AllowOnlyAlphanumericUserNames = false,
                  RequireUniqueEmail = true
              };
      
              // Configure validation logic for passwords
              manager.PasswordValidator = new PasswordValidator
              {
                  RequiredLength = 8,
                  // RequireNonLetterOrDigit = true,
                  RequireDigit = true,
                  RequireLowercase = true,
                  RequireUppercase = true,
              };
      
              // Configure user lockout defaults
              manager.UserLockoutEnabledByDefault = true;
              manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
              manager.MaxFailedAccessAttemptsBeforeLockout = 5;
      
              // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
              // You can write your own provider and plug it in here.
              manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser, int>
              {
                  MessageFormat = "Your security code is {0}"
              });
              manager.RegisterTwoFactorProvider("Email Code", 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;
          }
      }
      
      // Configure the application sign-in manager which is used in this application.
      public class ApplicationSignInManager : SignInManager<ApplicationUser, int>
      {
          public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
              : base(userManager, authenticationManager)
          {
          }
      
          public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
          {
              return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
          }
      
          public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
          {
              return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
          }
      }
      
    3. App_Start\Startup.Auth.cs 中将OnValidateIdentity 属性更改为:

      OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
          validateInterval: TimeSpan.FromMinutes(30),
          regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
          getUserIdCallback: id => id.GetUserId<int>())
      
    4. 更改 ManageController 以使用新的 pk 类型:

    User.Identity.GetUserId()的所有条目替换为User.Identity.GetUserId&lt;int&gt;()

    可能有几个字符串 id 参数需要更改为 int,但仅此而已。

    【讨论】:

    • 如果您能准确地突出代码中创建 int id 的内容,那就太好了。
    • 我们是否应该在用户表的 Id 字段上启用自动增量??
    • @niico - 据我所知,身份验证数据库中的 id 字段设置为自动递增
    • 嗨,我没有 OnValidateIdentity。这真的很重要吗?
    • 其他表键呢??像“角色”表或“用户角色”表。他们仍然是 nvarchar(MAX)!
    【解决方案2】:

    根据this blog post,使用 ASP.NET Core 标识进行以下更改:

    首先,转到Data\Migrations 文件夹并删除其中的所有内容。

    Startup.cs 中,在ConfigureServices 方法中,将services.AddIdentity 更改为

    services.AddIdentity<ApplicationUser, IdentityRole<int>>()
       .AddEntityFrameworkStores<ApplicationDbContext, int>()
       .AddDefaultTokenProviders();
    

    ApplicationDbContext.cs 中将基类从IdentityDbContext&lt;ApplicationUser&gt; 更改为

    public class ApplicationDbContext
      : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>
    

    最后,将ApplicationUser.cs中的基类从IdentityUser改为

    public class ApplicationUser : IdentityUser<int>
    

    然后运行add-migration -o Data\Migrationsupdate-database。如果迁移导致任何问题,请使用 Sql Server Management Studio 或 VS 中的 SqlServerObjectExplorer 删除数据库(不要只使用文件系统),重新删除迁移,然后重试。

    【讨论】:

    • @VulovicVukasin 只是想把这个网站上帮助我的人转给我能帮助的人。尽力而为
    • 对于 .NET Core 2.* 及更高版本,将 .AddEntityFrameworkStores&lt;ApplicationDbContext, int&gt;() 更改为 .AddEntityFrameworkStores&lt;ApplicationDbContext&gt;() 即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    相关资源
    最近更新 更多