背景

在需要进行表单认证的Asp.NET 5 MVC项目被创建后,往往需要根据项目的实际需求做一系列的工作对MVC 5内建的身份验证机制(Asp.NET Identity)进行扩展和定制:

  • Asp.NET内建的身份验证机制会使用Local DB(本地数据库)读写用户相关的信息,而在数据库驱动的项目中,管理业务信息的数据库通常是特定的数据库环境,比如远程SQL Server数据库实例或Access数据库等等,业务数据库中保存着一系列针对业务需求的数据表,因此需要定制MVC 5内建身份验证,使其操作的的用户表们与业务数据库的表们共处在同一数据库中
  • Asp.NET身份验证默认创建的用户表名为:AspNetRoles, AspNetUserClaims, AspNetUserLogins, AspNetUserRoles, AspNetUsers等,与实际业务数据库中自成体系的数据表命名习惯(如tblProduct, PRODUCT, Products...)不一致,因此需要定制MVC 5内建身份验证,使其使用我们指定的表名称保存用户信息,以便与实际业务数据库中的表名称处于相同的命名规范体系
  • 实际业务中用户信息往往多于Asp.NET默认提供的,如根据实际情况会需要以用户email登录,或在Users表中保存用户的guid,性别,地址,是否激活等等,因此需要对Asp.net创建的表,以及相应操作的代码进行扩展

总之,一切都是为了减轻管理的负担,提升工作效率,使项目整体变得更加优雅。

要点

本文仅聚焦在表单身份认证(Forms Authentication)的个性化定制

 

步骤

Step 1. 创建SQL Server数据库,并运行以下SQL,创建示例用户数据表

CREATE TABLE [dbo].[User]
(
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Login] [nvarchar](50) NOT NULL,
    [EMail] [nvarchar](255) NOT NULL,
    [Password] [nvarchar](500) NULL,
    [CreationDate] [datetime] NULL,
    [ApprovalDate] [datetime] NULL,
    [LastLoginDate] [datetime] NULL,
    [IsLocked] [bit] NOT NULL,
    [PasswordQuestion] [nvarchar](max) NULL,
    [PasswordAnswer] [nvarchar](max) NULL,
    [ActivationToken] [nvarchar](200) NULL,
    [EmailConfirmed] [bit] NOT NULL,
    [SecurityStamp] [nvarchar](max) NULL,
    [PhoneNumber] [nvarchar](50) NULL,
    [PhoneNumberConfirmed] [bit] NOT NULL,
    [TwoFactorEnabled] [bit] NOT NULL,
    [LockoutEndDateUtc] [datetime2](7) NULL,
    [LockoutEnabled] [bit] NOT NULL,
    [AccessFailedCount] [int] NOT NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    ),
     CONSTRAINT [UX_User_EMail] UNIQUE NONCLUSTERED 
    (
        [EMail] ASC
    ),
     CONSTRAINT [UX_User_Login] UNIQUE NONCLUSTERED 
    (
        [Login] ASC
    )
)
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_IsLocked]  DEFAULT ((0)) FOR [IsLocked]
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_EmailConfirmed]  DEFAULT ((0)) FOR [EmailConfirmed]
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_PhoneNumberConfirmed]  DEFAULT ((0)) FOR [PhoneNumberConfirmed]
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_TwoFactorEnabled]  DEFAULT ((0)) FOR [TwoFactorEnabled]
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_LockoutEnabled]  DEFAULT ((0)) FOR [LockoutEnabled]
GO
ALTER TABLE [dbo].[User] ADD  CONSTRAINT [DF_User_AccessFailCount]  DEFAULT ((0)) FOR [AccessFailedCount]
GO

CREATE TABLE [UserRegistrationToken]
(
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [UserId] [bigint] NULL,
    [Token] [nchar](10) NOT NULL,
    CONSTRAINT [PK_SecurityToken] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    ),
    CONSTRAINT [UX_UserRegistrationToken_Token] UNIQUE NONCLUSTERED 
    (
        [Token] ASC
    )
)
GO

CREATE TABLE [dbo].[Role] (
    [Id]   BIGINT IDENTITY (1, 1) NOT NULL,
    [Name] NVARCHAR (MAX) NOT NULL,
    CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED ([Id] ASC)
)
GO

CREATE TABLE [dbo].[UserRole] (
    [UserId] BIGINT NOT NULL,
    [RoleId] BIGINT NOT NULL,
    CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
    CONSTRAINT [FK_UserRole_Role] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[Role] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_UserRole_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE
)
GO

CREATE NONCLUSTERED INDEX [IX_RoleId]
    ON [dbo].[UserRole]([RoleId] ASC);
GO

CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[UserRole]([UserId] ASC);
GO

CREATE TABLE [dbo].[UserLogin] (
    [UserId]        BIGINT NOT NULL,
    [LoginProvider] NVARCHAR (128) NOT NULL,
    [ProviderKey]   NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_UserLogin] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [ProviderKey] ASC),
    CONSTRAINT [FK_UserLogin_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE
)
GO

CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[UserLogin]([UserId] ASC);
GO

CREATE TABLE [dbo].[UserClaim] (
    [Id]         BIGINT IDENTITY (1, 1) NOT NULL,
    [UserId]     BIGINT NOT NULL,
    [ClaimType]  NVARCHAR (MAX) NULL,
    [ClaimValue] NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_UserClaim] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_UserClaim_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE
)
GO

CREATE NONCLUSTERED INDEX [IX_User_Id]
    ON [dbo].[UserClaim]([UserId] ASC);

GO
View Code

Step 2. 创建MVC示例项目

运行Visual Studio 2013 -> 新建项目 -> Visual C# -> Web -> ASP.NET Web Application,输入MVC项目的名称,确定

定制与扩展Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

在接下来的项目设置界面中,选择MVC项目,认证方式选择"个别用户帐户"

定制与扩展Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

Step 3. 创建单独的类库,用于保存业务模型,数据库关系映射,业务逻辑等

  实际项目中,我个人很喜欢把业务模型,数据库关系映射,业务逻辑等根据实际情况放到独立的类库项目中。即使很小型的简单项目,也会至少把与前端表示层不相关的代码归拢到一个类库里面,便于管理

  解决方案浏览器中右击解决方案节点 -> "添加..." -> 新项目

  定制与扩展Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

  新建项目窗口中,选择Visual C# -> Windows -> 类库 -> 输入项目名称 (本例中用Core命名) -> 确定 -> 删除自动创建的Class1.cs

  定制与扩展Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

Step 4. 更新MVC项目中的数据库连接字符串

  因为我们的目标是使用自己的数据库而非Asp.NET默认的,因此需要首先修改MVC项目中的连接字符串

  打开Web.config,找到<connectionStrings>节点,对名为DefaultConnection的connectionString进行修改:

<add name="DefaultConnection" connectionString="Server=myserver;Database=mydatabase;User Id=myuserid;Password=mypassword;" providerName="System.Data.SqlClient" />

Step 5. 在类库项目中引用所需的Nuget包

  Microsoft ASP.NET Identity Owin和Microsoft ASP.NET Identity Framework,本项目中引用的这两个包的版本为2.2.1

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-01-17
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-23
猜你喜欢
  • 2021-11-25
  • 2022-12-23
  • 2021-07-01
  • 2021-08-29
  • 2021-12-27
相关资源
相似解决方案