我有一个使用Identity在MVC5上构建的Web应用程序。我想将此项目转换为ASP.NET Core 2.2 Web应用程序。我创建了一个新的ASP.NET Core 2.2 Web应用程序,其身份验证设置为“个人用户帐户”,并按照these instructions将数据库添加到项目中。然后,我在项目中添加了一个新的Identity Scaffolded项目,并添加了迁移并更新了数据库。
我注册了一个测试用户,当我检查SQL管理服务器时,我看到它为该项目创建了一个新数据库,即使我的连接字符串适用于旧数据库也是如此。
我想保留我的旧数据库,但是将其转换为使用ASP.NET Core内置的新Identity Razor页面。最好的方法是什么?
答案 0 :(得分:4)
升级身份表后,您可能想要更新现有用户密码哈希。 AspNetUsers
表中的某些新列将具有NULL
值。首先运行:
UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(Email)
WHERE NormalizedEmail IS NULL
NormalizedUserName实际上是用大写的电子邮件更新的。
我们需要一种方法来区分哪些用户正在使用新的哈希版本。
一种方法是向IdentityUser添加新属性:
public class ApplicationUser : IdentityUser
{
public PasswordHashVersion HashVersion { get; set; }
public ApplicationUser()
{
this.HashVersion = PasswordHashVersion.Core;
}
}
public enum PasswordHashVersion
{
OldMvc,
Core
}
现有用户的默认PasswordHashVersion
等于零(OldMvc),新注册的用户默认值为1(Core)。如果您有一种更聪明的方法来检测哈希是来自新算法还是旧算法,则不需要。
然后,我们创建一个使用old default hash algorithm implementation的自定义PasswordHash:
public class OldMvcPasswordHasher : PasswordHasher<ApplicationUser>
{
public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
{
// if it's the new algorithm version, delegate the call to parent class
if (user.HashVersion == PasswordHashVersion.Core)
return base.VerifyHashedPassword(user, hashedPassword, providedPassword);
byte[] buffer4;
if (hashedPassword == null)
{
return PasswordVerificationResult.Failed;
}
if (providedPassword == null)
{
throw new ArgumentNullException("providedPassword");
}
byte[] src = Convert.FromBase64String(hashedPassword);
if ((src.Length != 0x31) || (src[0] != 0))
{
return PasswordVerificationResult.Failed;
}
byte[] dst = new byte[0x10];
Buffer.BlockCopy(src, 1, dst, 0, 0x10);
byte[] buffer3 = new byte[0x20];
Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(providedPassword, dst, 0x3e8))
{
buffer4 = bytes.GetBytes(0x20);
}
if (AreHashesEqual(buffer3, buffer4))
{
user.HashVersion = PasswordHashVersion.Core;
return PasswordVerificationResult.SuccessRehashNeeded;
}
return PasswordVerificationResult.Failed;
}
private bool AreHashesEqual(byte[] firstHash, byte[] secondHash)
{
int _minHashLength = firstHash.Length <= secondHash.Length ? firstHash.Length : secondHash.Length;
var xor = firstHash.Length ^ secondHash.Length;
for (int i = 0; i < _minHashLength; i++)
xor |= firstHash[i] ^ secondHash[i];
return 0 == xor;
}
}
此类继承了新的Identity Core PasswordHasher
。如果用户的密码哈希版本已在使用新算法(例如HashVersion = Core),则我们只需从PasswordHasher
调用使用新算法的基本方法即可。否则,请使用旧的身份算法来验证密码。
如果密码匹配,我们会将用户密码哈希版本更新为Core
,然后返回PasswordVerificationResult.SuccessRehashNeeded
,以使用新算法强制更新现有哈希。
最后,您需要确保使用了自定义PasswordHasher
。将其添加到Startup.cs
内的ConfigureServices
:
// Replace the existing scoped IPasswordHasher<> implementation
services.Replace(new ServiceDescriptor(
serviceType: typeof(IPasswordHasher<ApplicationUser>),
implementationType: typeof(OldMvcPasswordHasher),
ServiceLifetime.Scoped));
必须在对
AddIdentity
,AddDefaultIdentity
或AddIdentityCore
进行任何调用之后将其添加。
这将在您的用户进行身份验证时缓慢更新密码哈希。
答案 1 :(得分:3)
我能够按照以下步骤将.NET 4.5.2项目成功迁移到.NET Core 3.1
Scaffold-DbContext
基于现有数据库[1] Scaffold-DbContext [-Connection] [-Provider] [-OutputDir] [-Context] [-Schemas>] [-Tables>] [-DataAnnotations] [-Force] [-Project] [-StartupProject] [<CommonParameters>]
从生成的上下文以及不再需要的.cs文件中删除所有与AspNet相关的表。
将base.OnModelCreating(modelBuilder);
添加到上下文文件中生成的OnModelCreating
方法中。 [2]
ALTER TABLE ASPNETROLES
ADD
ConcurrencyStamp VARCHAR(255) NULL,
NormalizedName VARCHAR(255) NULL
DROP TABLE AspNetUserTokens
CREATE TABLE [AspNetUserTokens] (
[UserId] NVARCHAR (450) NOT NULL,
[LoginProvider] NVARCHAR (450) NOT NULL,
[Name] NVARCHAR (450) NOT NULL,
[Value] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_AspNetUserTokens]
PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [Name] ASC)
)
ALTER TABLE AspNetUsers
ADD
ConcurrencyStamp VARCHAR(255) NULL,
LockoutEnd DATETIME NULL,
NormalizedEmail VARCHAR(255) NULL,
NormalizedUserName VARCHAR(255) NULL
DROP TABLE [AspNetRoleClaims]
CREATE TABLE [AspNetRoleClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
[RoleId] NVARCHAR (128) NOT NULL,
CONSTRAINT [PK_AspNetRoleClaims]
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId]
FOREIGN KEY ([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE
)
GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId]
ON [AspNetRoleClaims]([RoleId] ASC)
ALTER TABLE AspNetUserLogins
ADD ProviderDisplayName VARCHAR(255) NULL
UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(UserName)
WHERE NormalizedEmail IS NULL
Startup.cs
文件上,设置密码散列器兼容模式以考虑IdentityV2 services.Configure<PasswordHasherOptions>(options => options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2);
答案 2 :(得分:1)
我已经编写了用于迁移到 AspNetCore身份的SQL脚本。
此脚本与 AspNet Identity 完全向后兼容,因为我已向表中添加了新列并扩展了已经存在的列。
让我们看一下通过Scheme compare生成的屏幕截图:
下面您可以看到最终的脚本
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET XACT_ABORT ON;
GO
PRINT N'Starting dropping constraints';
GO
ALTER TABLE [dbo].[AspNetUserRoles]
DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId];
GO
ALTER TABLE [dbo].[AspNetUserRoles]
DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId];
GO
ALTER TABLE [dbo].[AspNetUserClaims]
DROP CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId];
GO
ALTER TABLE [dbo].[AspNetUserLogins]
DROP CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId];
-----------------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetRoles]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetRoles] (
[Id] NVARCHAR (450) NOT NULL,
[Name] NVARCHAR (256) NULL,
[NormalizedName] NVARCHAR (256) NULL,
[ConcurrencyStamp] NVARCHAR (MAX) NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetRoles1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetRoles])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetRoles] ([Id], [Name], [NormalizedName], [ConcurrencyStamp])
SELECT [Id],
[Name],
UPPER([Name]),
NEWID()
FROM [dbo].[AspNetRoles]
ORDER BY [Id] ASC;
END
DROP TABLE [dbo].[AspNetRoles];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetRoles]', N'AspNetRoles';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetRoles1]', N'PK_AspNetRoles', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex]
ON [dbo].[AspNetRoles]([Name] ASC) WHERE ([Name] IS NOT NULL) WITH (FILLFACTOR = 80);
GO
CREATE UNIQUE NONCLUSTERED INDEX [RoleNormalizedNameIndex]
ON [dbo].[AspNetRoles]([NormalizedName] ASC) WHERE ([NormalizedName] IS NOT NULL) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserClaims]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[UserId] NVARCHAR (450) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserClaims1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserClaims])
BEGIN
SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] ON;
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserClaims] ([Id], [UserId], [ClaimType], [ClaimValue])
SELECT [Id],
[UserId],
[ClaimType],
[ClaimValue]
FROM [dbo].[AspNetUserClaims]
ORDER BY [Id] ASC;
SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] OFF;
END
DROP TABLE [dbo].[AspNetUserClaims];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserClaims]', N'AspNetUserClaims';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserClaims1]', N'PK_AspNetUserClaims', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId]
ON [dbo].[AspNetUserClaims]([UserId] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserLogins]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserLogins] (
[LoginProvider] NVARCHAR (450) NOT NULL,
[ProviderKey] NVARCHAR (450) NOT NULL,
[ProviderDisplayName] NVARCHAR (MAX) NULL,
[UserId] NVARCHAR (450) NOT NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserLogins1] PRIMARY KEY CLUSTERED ([LoginProvider] ASC, [ProviderKey] ASC, [UserId] ASC) WITH (FILLFACTOR = 80)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserLogins])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserLogins] ([LoginProvider], [ProviderKey], [UserId])
SELECT [LoginProvider],
[ProviderKey],
[UserId]
FROM [dbo].[AspNetUserLogins]
ORDER BY [LoginProvider] ASC, [ProviderKey] ASC;
END
DROP TABLE [dbo].[AspNetUserLogins];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserLogins]', N'AspNetUserLogins';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserLogins1]', N'PK_AspNetUserLogins', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId]
ON [dbo].[AspNetUserLogins]([UserId] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserRoles]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserRoles] (
[UserId] NVARCHAR (450) NOT NULL,
[RoleId] NVARCHAR (450) NOT NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserRoles1] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC) WITH (FILLFACTOR = 80)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUserRoles])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetUserRoles] ([UserId], [RoleId])
SELECT [UserId],
[RoleId]
FROM [dbo].[AspNetUserRoles]
ORDER BY [UserId] ASC, [RoleId] ASC;
END
DROP TABLE [dbo].[AspNetUserRoles];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserRoles]', N'AspNetUserRoles';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserRoles1]', N'PK_AspNetUserRoles', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId]
ON [dbo].[AspNetUserRoles]([RoleId] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUsers]...';
GO
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
CREATE TABLE [dbo].[tmp_ms_xx_AspNetUsers] (
[Id] NVARCHAR (450) NOT NULL,
[Email] NVARCHAR (256) NULL,
[NormalizedEmail] NVARCHAR (256) NULL,
[EmailConfirmed] BIT NOT NULL,
[PasswordHash] NVARCHAR (MAX) NULL,
[SecurityStamp] NVARCHAR (MAX) NULL,
[PhoneNumber] NVARCHAR (MAX) NULL,
[PhoneNumberConfirmed] BIT NOT NULL,
[TwoFactorEnabled] BIT NOT NULL,
[LockoutEndDateUtc] DATETIME NULL,
[LockoutEnd] DATETIMEOFFSET (7) NULL,
[LockoutEnabled] BIT NOT NULL,
[AccessFailedCount] INT NOT NULL,
[UserName] NVARCHAR (256) NULL,
[NormalizedUserName] NVARCHAR (256) NULL,
[ConcurrencyStamp] NVARCHAR (MAX) NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUsers1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
);
IF EXISTS (SELECT TOP 1 1
FROM [dbo].[AspNetUsers])
BEGIN
INSERT INTO [dbo].[tmp_ms_xx_AspNetUsers] (
[Id],
[Email],
[NormalizedEmail],
[EmailConfirmed],
[PasswordHash],
[SecurityStamp],
[PhoneNumber],
[PhoneNumberConfirmed],
[TwoFactorEnabled],
[LockoutEnabled],
[AccessFailedCount],
[UserName],
[NormalizedUserName],
[ConcurrencyStamp])
SELECT [Id],
[Email],
UPPER([Email]),
[EmailConfirmed],
[PasswordHash],
[SecurityStamp],
[PhoneNumber],
[PhoneNumberConfirmed],
[TwoFactorEnabled],
[LockoutEnabled],
[AccessFailedCount],
[UserName],
UPPER([UserName]),
NEWID()
FROM [dbo].[AspNetUsers]
ORDER BY [Id] ASC;
END
DROP TABLE [dbo].[AspNetUsers];
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUsers]', N'AspNetUsers';
EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUsers1]', N'PK_AspNetUsers', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[AspNetUsers]([UserName] ASC) WHERE ([UserName] IS NOT NULL) WITH (FILLFACTOR = 80);
GO
CREATE UNIQUE NONCLUSTERED INDEX [NormalizedUserNameIndex]
ON [dbo].[AspNetUsers]([NormalizedUserName] ASC) WHERE ([NormalizedUserName] IS NOT NULL) WITH (FILLFACTOR = 80);
GO
CREATE NONCLUSTERED INDEX [EmailIndex]
ON [dbo].[AspNetUsers]([NormalizedEmail] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
CREATE TABLE [dbo].[AspNetRoleClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[RoleId] NVARCHAR (450) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
);
GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId]
ON [dbo].[AspNetRoleClaims]([RoleId] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Creating [dbo].[AspNetUserTokens]...';
GO
CREATE TABLE [dbo].[AspNetUserTokens] (
[UserId] NVARCHAR (450) NOT NULL,
[LoginProvider] NVARCHAR (450) NOT NULL,
[Name] NVARCHAR (450) NOT NULL,
[Value] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [Name] ASC) WITH (FILLFACTOR = 80)
);
-------------------------------------------------------------------
GO
PRINT N'Creating [dbo].[__EFMigrationsHistory]...';
GO
CREATE TABLE [dbo].[__EFMigrationsHistory] (
[MigrationId] NVARCHAR (150) NOT NULL,
[ProductVersion] NVARCHAR (32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY CLUSTERED ([MigrationId] ASC) WITH (FILLFACTOR = 80)
);
--GO
--INSERT INTO [dbo].[__EFMigrationsHistory]
-- ([MigrationId], [ProductVersion])
--VALUES
-- ('20200406184458_InitialCreate', '2.2.6-servicing-10079')
-------------------------------------------------------------------
GO
PRINT N'Creating constraints';
GO
ALTER TABLE [dbo].[AspNetUserLogins] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[AspNetRoleClaims] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[AspNetUserTokens] WITH NOCHECK
ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
-------------------------------------------------------------------
GO
PRINT N'Update complete.';
COMMIT TRANSACTION;
答案 3 :(得分:0)
尽管Microsoft documentation有所帮助。最有用的信息是在评论中。
我能够使用以下步骤迁移现有数据库:
创建一个新的ASP.net Core项目并将其ModelSnapshot修改为
与EF6匹配。之后,您可以为chnages生成脚本
EF6到EF Core。
编写脚本以更新AspNetUsers表。在ASP.net核心中
身份验证时使用的身份NormalizedEmail,
NormalizedUserName列。所以我们需要更新这两列
使用我们现有的数据。
这是脚本的GitHub链接,用于更新表。 Migration.zip
答案 4 :(得分:0)
另一种解决方案是将数据导出/导入到新表中。这是出于几个不同的原因而做的,但是最终不想更改我的原始源表,以防万一我需要快速轻松地返回它。
长话短说,您可以将旧数据直接导入/导出到新的Identity表中,唯一需要做的就是标准化的用户名和电子邮件值。
如果Identity能够在内部处理(更新)新密码哈希,安全性戳记和并发性戳记,而在用户首次登录时没有问题,则可以在内部进行处理,那就太好了。
我使用完整的密码迁移用户的超级快捷方式:
1)将旧版本的Identity上的users表导出到CSV文件。
2)在Excel中打开该csv文件,并在CSV文件中为三个缺少的规范化列(用户名和电子邮件)和一个缺少的并发戳记列(未真正需要并发列)添加三列)。
3)在第一个空白标准化列(通常为c2)中,添加Excel公式=UPPER(b2)
(其中b2是您要标准化的第一个值的字段...例如,在直接导出中将Username = b2或Email = d2放在其中,将标准化列放在非标准化列旁边。按Enter键,您现在应该在字段中看到大写字母值。
4)将该公式向下拖动到电子表格的末尾,以将所有用户名和电子邮件标准化为它们的大写值(即所有大写=标准化)。
5)将大写值从电子表格中复制并粘贴到一个空的记事本文件中...然后将它们复制回电子表格中的同一位置(这将用规范化的公式覆盖公式Excel可能足够聪明,可以摆脱公式并将标准化的值保存在CSV保存中,但我没有对其进行测试。
6)将电子表格另存为CSV并将其导入到新的身份AspnetUsers表中。
并发标记可以保留为空白,并且当用户首次登录时,最新的身份将负责其他所有事情。
如果您尚未在新版本中启用用户名,也不会在旧版本中启用用户名,那么该身份也不会登录(因此您需要先启用该功能或将用户名转换为相关的电子邮件地址,然后才能成功登录) )。
这不是一件很漂亮的事情,但是对于一次工作,我用不到15分钟的时间便用这种方法将用户从Identity 4.0.30319迁移到Core 2.2,并且不需要更改密码。我输入所有这些内容所花的时间比迁移用户所需的时间长。希望对您有所帮助。