擴展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_Start\IdentityConfig.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_Start\Startup.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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章