zoukankan      html  css  js  c++  java
  • 扩展ASP.NET Identity使用Int做主键

    当我们默认新建一个ASP.NET MVC项目的时候,使用的身份认证系统是ASP.NET Identity.
    但是这里的Identity使用的主键为String类型的GUID.当然这是大多数系统首先类型.
    但是因为历史原因,而我们公司所有项目主键都是用的Int类型(这里不讨论int和GUID的优劣)
    所以默认的String类型GUID就不能满足我们的需求,所以进行一些扩展,让其支持Int类型。
    下图为默认使用String做主键的ASP.NET MVC
    QQ截图20150624104458

    ApplicationUser继承自IdentityUser,而IdentityUser继承/实现
    IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
    这样就使得主键为string类型了,其中IentityUser,IdentityUserLogin,IdentityUserRole,IdentityUserClaim都是<string>
    所以生成默认的数据库里的表结构成了下图这样,主键都为nvarchar
    QQ截图20150624105533QQ截图20150624105623

    接下来,扩展为Int主键首先增加如下几个类

    public class ApplicationUserLogin : IdentityUserLogin<int> { }
        public class ApplicationUserCliam : IdentityUserClaim<int> { }
        public class ApplicationUserRole : IdentityUserRole<int> { }
        public class ApplicationRole : IdentityRole<int, ApplicationUserRole>, IRole<int> {
            public string Description { get; set; }
            public ApplicationRole() { }
            public ApplicationRole(string name)
                : this()
            {
                this.Name = name;
            }
            public ApplicationRole(string name, string description)
                : this(name)
            {
                this.Description = description;
            }
        }
    ApplicationUserLogin  继承自IdentityUserLogin<int>
    ApplicationUserCliam  继承自IdentityUserClaim<int>
    ApplicationUserRole   继承自IdentityUserRole<int>
    ApplicationRole       继承自IdentityRole<int, ApplicationUserRole>, IRole<int>
    在Role里还增加了一个属性Deacription(默认实体里只有Id,Name)
    做了这步后。其实在Code first中,我们就已经把实体的结构主键修改为int型了,
    只要用这个对应实体Update到数据库中的话。主键会修改成int
    然后我们还要对应ASP.NET MVC的一些改造才可以适应现有的模板
    然后我们将ApplicationUser修改
    public class ApplicationUser : IdentityUser
        {
            public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
            {
                // 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配
                var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
                // 在此处添加自定义用户声明
                return userIdentity;
            }
        }

    修改为:

    public class ApplicationUser 
            : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserCliam>, IUser<int>
        {
            public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager)
            {
                // 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配
                var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
                // 在此处添加自定义用户声明
                return userIdentity;
            }
        }

    接下来我们要修改数据库上下文ApplicationDbContext
    QQ截图20150624112544
    修改为

    public class ApplicationDbContext 
            : IdentityDbContext<ApplicationUser, ApplicationUserRole, int, 
            ApplicationUserLogin, ApplicationUserRole, ApplicationUserCliam>
        {
            public ApplicationDbContext()
                : base("DefaultConnection")
            {
            }
            public static ApplicationDbContext Create()
            {
                return new ApplicationDbContext();
            }
        }

    然后在增加如下两个类

    public class ApplicationUserStore
            : UserStore<ApplicationUser, ApplicationRole, int,
            ApplicationUserLogin, ApplicationUserRole, ApplicationUserCliam>,
            IUserStore<ApplicationUser, int>, 
            IDisposable
        {
            public ApplicationUserStore(DbContext context)
                : base(context)
            { }
            public ApplicationUserStore()
                : this(new IdentityDbContext())
            {
                base.DisposeContext = true;
            }
        }
        public class ApplicationRoleStore
            : RoleStore<ApplicationRole, int, ApplicationUserRole>,
            IQueryableRoleStore<ApplicationRole, int>,
            IRoleStore<ApplicationRole>,
            IDisposable
        {
            public ApplicationRoleStore()
                : base(new IdentityDbContext())
            {
                base.DisposeContext = true;
            }
    
        </span><span style="color: #0000ff">public</span><span style="color: #000000"> ApplicationRoleStore(DbContext context)
            : </span><span style="color: #0000ff">base</span><span style="color: #000000">(context)
        {
        }
    }</span></pre></div>
    

    上面的几处代码全修改在IdentityModels.cs文件中

    然后修改App_StartIdentityConfig.cs
    在类ApplicationUserManager和ApplicationSignInManager中
    把里面所有继承自<ApplicationRole>泛型的地址全部都修改为<ApplicationRole,int>
    public class ApplicationUserManager : UserManager<ApplicationUser,int>
    public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
    manager.UserValidator = new UserValidator<ApplicationUser, int>(manager)
    manager.RegisterTwoFactorProvider("电话代码", new PhoneNumberTokenProvider<ApplicationUser,int>
    manager.RegisterTwoFactorProvider("电子邮件代码", new EmailTokenProvider<ApplicationUser,int>
    public class ApplicationSignInManager : SignInManager<ApplicationUser, int>

    在App_StartStartup.Auth.cs
    把配置登陆Cookie的代码修改为

    app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login"),
                    Provider = new CookieAuthenticationProvider
                    {
                        // 当用户登录时使应用程序可以验证安全戳。
                        // 这是一项安全功能,当你更改密码或者向帐户添加外部登录名时,将使用此功能。
                        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
                            validateInterval: TimeSpan.FromMinutes(30),
                            regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                            getUserIdCallback: (claim) => int.Parse(claim.GetUserId()))
                        //regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                    }
                });
    到此,所有的扩展都已经修改完成,接下来就只要修改相关的View和Controller
    在AccountController和ManageController中,
    主要是把用到User.Identity.GetUserId()的地方修改为User.Identity.GetUserId<int>();
    这样使得拿到的主键由string变成了int

    接下来运行程序包管理控制台,生成数据库脚本并执行到数据库

    PM> Enable-Migrations
    正在检查上下文的目标是否为现有数据库...
    已为项目 IntegerDemo 启用 Code First 迁移。
    PM> Add-Migration FirstInit
    正在为迁移“FirstInit”搭建基架。
    此迁移文件的设计器代码包含当前 Code First 模型的快照。在下一次搭建迁移基架时,将使用此快照计算对模型的更改。如果对要包含在此迁移中的模型进行其他更改,则您可通过再次运行“Add-Migration FirstInit”重新搭建基架。
    PM> Update-Database
    指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
    正在应用显式迁移: [201506240620390_FirstInit]。
    正在应用显式迁移: 201506240620390_FirstInit。
    正在运行 Seed 方法。

    再看我们的数据库,已经把主键全都变成了int
    QQ截图20150624142400QQ截图20150624142412

    相关文档资料
    http://www.asp.net/identity
    http://typecastexception.com/post/2014/07/13/ASPNET-Identity-20-Extending-Identity-Models-and-Using-Integer-Keys-Instead-of-Strings.aspx
    转载请标明出处:http://giantliu.com

  • 相关阅读:
    mysql的存储过程
    一份php高级工程师的面试题,我每天看一点点
    php的常用函数(持续更新)
    php 中文字符串截取
    php递归遍历文件目录
    ajax timeout 断网处理
    angular 刷新问题
    angular state中templateUrl 路径的模板
    angular请求传递不了数据
    截取字符串 substring substr slice
  • 原文地址:https://www.cnblogs.com/liuju150/p/4597630.html
Copyright © 2011-2022 走看看