One of the first issues you will likely encounter when getting started with ASP.NET Identity centers on customizing the underlying data model. The Entity Framework provider uses Code-First to generate the data model and, initially, it may seem as if it is imposing its model upon your application. Fortunately, since the implementation of the provider uses Code-First, we can make significant customizations to the model and still take advantage of the features that ASP.NET Identity and EF provide.

In part one of this series, we will customize the ASP.NET Identity data model by simply changing the default schema and renaming the tables. In part two of this series, we will add audit fields to some of the tables and change the primary key data types from GUIDs to integers.

To get started, let’s generate the default data model to see what we are working with:

  1. Start by creating a new ASP.NET MVC and/or Web API project. Be sure the Authentication Mode is set to “Individual User Accounts” so the project template pulls in the required references, as well as the scaffolding for the default security model.
  2. Update the default connection string (“DefaultConnection”) in the web.config to point to your SQL Server database.
  3. Build and run the application.

Next, navigate to the login page and attempt to sign in with any credentials. Your login attempt will fail because no accounts are registered, but the Entity Framework should have generated the default data model for users, roles, and claims. If you check the database, you will find something similar to the following:

That is all well and good and if you have worked with the Membership Provider for .NET, you should be reasonably comfortable with what you see. However, we are interested in customizing the model; so let’s get started by renaming the tables and moving them into our application schema.

Step 1: Create the object model

To get started, add the following classes to your project. These classes form the object model that will be mapped to the data model. If you are following along in the attached sample project, you will find these classes under the NAM_Sample_Pt1.Models namespace.

ApplicationUserRole.cs

public class ApplicationUserRole : IdentityUserRole { }

ApplicationRole.cs

public class ApplicationRole : IdentityRole<string, applicationuserrole=""> { }

ApplicationUserClaim.cs

public class ApplicationUserClaim : IdentityUserClaim { }

ApplicationUserLogin.cs

public class ApplicationUserLogin : IdentityUserLogin { }

IdentityModels.cs

Update the ApplicationUser class with the following:

public class ApplicationUser : IdentityUser<string, applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">
{
    public async Task 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;
    }

Step 2: Create the EF data context

Create a new security data context in IdentityModels.cs according to the following definition:

public class ApplicationDbContext : IdentityDbContext<applicationuser, applicationrole,="" string,="" applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">
{
    public ApplicationDbContext() : base("DefaultConnection") { }     public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

Note that the data context inherits from IdentityDbContext, which is the generic base data context that is included in the EF Provider for Identity. IdentityDbContext includes several generic type parameters, which should be set to the various types defined in the object model we created in the previous step.

We will revisit the data context once we have finished configuring the objects required to customize the model; however, be aware that this is where we will implement the fluent mapping.

Step 3: Create a custom user store

In ASP.NET Identity 2.0 user stores are the repositories for user data. The Entity Framework implementation of the user store requires a data context. Here is the implementation of our custom user store:

public class ApplicationUserStore :
    UserStore<applicationuser, applicationrole,="" string,="" applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">,
    IUserStore,
   IDisposable
{
    public ApplicationUserStore(ApplicationDbContext context) : base(context) { }
}

Step 4: Modify ApplicationUserManager to use the new object model

There are several lines in the ApplicationUserManager (included in the default project template) that must be modified. First, in the static Create() method, modify the creation of the ApplicationUserManager so that it takes an ApplicationUserStore and ApplicationDbContext as arguments in its constructor, as such:

        var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get()));

Step 5: Create the fluent mapping

We are finally ready to map our objects to our new data model. Begin by overriding OnModelCreating() in ApplicationDbContext . We will use EF Fluent API to map each of the five objects in our security object model to new tables in a new schema. The full fluent API mapping is included below:

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        {
            modelBuilder.HasDefaultSchema("NAM");             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserLogin");
                c.Properties(p => new
                {
                    p.UserId,
                    p.LoginProvider,
                    p.ProviderKey
                });
            }).HasKey(p => new { p.LoginProvider, p.ProviderKey, p.UserId });             // Mapping for ApiRole
            modelBuilder.Entity().Map(c =>
            {
                c.ToTable("Role");
                c.Property(p => p.Id).HasColumnName("RoleId");
                c.Properties(p => new
                {
                    p.Name
                });
            }).HasKey(p => p.Id);
            modelBuilder.Entity().HasMany(c => c.Users).WithRequired().HasForeignKey(c => c.RoleId);
            
            modelBuilder.Entity().Map(c =>
            {
                c.ToTable("User");
                c.Property(p => p.Id).HasColumnName("UserId");
                c.Properties(p => new
                {
                    p.AccessFailedCount,
                    p.Email,
                    p.EmailConfirmed,
                    p.PasswordHash,
                    p.PhoneNumber,
                    p.PhoneNumberConfirmed,
                    p.TwoFactorEnabled,
                    p.SecurityStamp,
                    p.LockoutEnabled,
                    p.LockoutEndDateUtc,
                    p.UserName
                });
            }).HasKey(c => c.Id);
            modelBuilder.Entity().HasMany(c => c.Logins).WithOptional().HasForeignKey(c => c.UserId);
            modelBuilder.Entity().HasMany(c => c.Claims).WithOptional().HasForeignKey(c => c.UserId);
            modelBuilder.Entity().HasMany(c => c.Roles).WithRequired().HasForeignKey(c => c.UserId);             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserRole");
                c.Properties(p => new
                {
                    p.UserId,
                    p.RoleId
                });
            })
            .HasKey(c => new { c.UserId, c.RoleId });             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserClaim");
                c.Property(p => p.Id).HasColumnName("UserClaimId");
                c.Properties(p => new
                {
                    p.UserId,
                    p.ClaimValue,
                    p.ClaimType
                });
            }).HasKey(c => c.Id);
        }

You are now ready to build and run the project. As before, navigate to the login page and attempt to sign in, which will force the creation of the new data model. You should now see the model in the custom schema with the table names we declared in the fluent mapping.

In part two of this series we will add audit fields to some of the tables and change the primary key data types from GUIDs to integers.

 

Attachments

Web API 2 自定义默认Identity Table Name的更多相关文章

  1. Web API配置自定义路由

    默认访问Web API时,是无需指定method名.它会按照默认的路由来访问.如果你的Web API中出现有方法重载时,也许得配置自定义路由: 标记1为自定义路由,标记2为默认路由,需要把自定义路由排 ...

  2. Web API 基于ASP.NET Identity的Basic Authentication

    今天给大家分享在Web API下,如何利用ASP.NET Identity实现基本认证(Basic Authentication),在博客园子搜索了一圈Web API的基本认证,基本都是做的Forms ...

  3. 一张图说明 Web Api 参数绑定默认规则

    请求如下: 控制器如下: 慎重说明:不管请求方式是 get 还是 post , 简单类型的参数,如 name 和 id ,其值都是从 url 里面去取. Web API 从 url 还是 body 获 ...

  4. [Asp.Net web api]基于自定义Filter的安全认证

    摘要 对第三方开放的接口,处于安全的考虑需要对其进行安全认证,是否是合法的请求.目前在项目中也遇到这种情况,提供的接口因为涉及到客户铭感数据,所以在调用的时候,不能直接暴露,需要有一个认证的机制.所以 ...

  5. ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)

    GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...

  6. YbSoftwareFactory 代码生成插件【十三】:Web API 的安全性

    ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.Android设备.IOS等) ...

  7. ASP.NET MVC4中调用WEB API的四个方法

    http://tech.it168.com/a2012/0606/1357/000001357231_all.shtml [IT168技术]当今的软件开发中,设计软件的服务并将其通过网络对外发布,让各 ...

  8. Web API 的安全性

    Web API 的安全性 ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.An ...

  9. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

随机推荐

  1. 测试工具使用-Qunit单元测试使用过程

    031302620 应课程要求写一篇单元测试工具的博客,但是暂时没用到java,所以不想使用junit(对各种类都不熟悉的也不好谈什么测试),原计划是要用phpunit,但是安装经历了三个小时,查阅各 ...

  2. Google机器学习课程基于TensorFlow : https://developers.google.cn/machine-learning/crash-course

    Google机器学习课程基于TensorFlow  : https://developers.google.cn/machine-learning/crash-course         https ...

  3. UVA12298 Super Poker II

    怎么又是没人写题解的UVA好题,个人感觉应该是生成函数的大板子题了. 直接做肯定爆炸,考虑来一发优化,我们记一个多项式,其中\(i\)次项的系数就表示对于\(i\)这个数有多少种表示方式. 那么很明显 ...

  4. go项目

    1.循环使用缓存 每条日志需要开辟缓存块来存储内容,以减少频繁的内存分配与回收.日志结构体定义如下: type MLogger struct { // freeList is a list of by ...

  5. vue内置组件 transition 和 keep-alive 使用

    1.transition name - string,用于自动生成 CSS 过渡类名.例如:name: 'fade' 将自动拓展为.fade-enter,.fade-enter-active等.默认类 ...

  6. Linux提示删除文件cannot remove `文件名': Operation not permitted

    Linux系统下删除某个文件时提示如下报错: 执行lsattr命令可以看到隐藏属性-------i--------,如下图: 通过查找资料发现: chattr命令用于改变文件属性.这项指令可改变存放在 ...

  7. git rebase的用法

    改变基 一个git库,开发人员在master分支的Bcommit的时候,创建了一个dev分支,此时Bcommit是dev分支的基,然后分别进行两个分支的开发. 进行到master提交了Dcommit, ...

  8. MyEclipse配置tomcat报错 - java.lang.UnsupportedClassVersionError: org/apache/lucene/store/Directory : Unsupported major.minor version 51.0

    1 开发Servlet程序时,MyEclipse配置好tomcat与JDK之后,启动时控制台报下列错误: 1 java.lang.UnsupportedClassVersionError: org/a ...

  9. Chrome 浏览器的简单设置 无痕模式 暗黑模式 自定义用户目录

    1. Chrome73 新增加了暗黑模式 可以通过修改快捷方式的方式来默认开启方法如下 1.1 关闭浏览器 2.2 鼠标焦点定位到任务栏 Chrome 图标处, 并且按住shift 按键 执行右键操作 ...

  10. Oracle可视化工具PL/SQL Developer的安装与配置

    安装程序: 安装目录不能有中文和空格,否则无法进行远程连接. 推荐使用 D:\PLSQLDeveloper 为安装目录 破解PLSQLDeveloper 使用工具 PLSQL Developer10. ...