Migração de um site existente da Associação do SQL para a Identidade do ASP.NET
por Rick Anderson, Suhas Joshi
Este tutorial ilustra as etapas para migrar um aplicativo Web existente com dados de usuário e função criados usando a Associação sql para o novo sistema de identidade ASP.NET. Essa abordagem envolve alterar o esquema de banco de dados existente para aquele necessário para o ASP.NET Identity e conectar as classes antigas/novas a ele. Depois de adotar essa abordagem, depois que o banco de dados for migrado, as atualizações futuras para a Identidade serão tratadas sem esforço.
Para este tutorial, vamos usar um modelo de aplicativo Web (Web Forms) criado usando o Visual Studio 2010 para criar dados de usuário e função. Em seguida, usaremos scripts SQL para migrar o banco de dados existente para tabelas necessárias para o sistema de identidade. Em seguida, instalaremos os pacotes NuGet necessários e adicionaremos novas páginas de gerenciamento de conta que usam o sistema de identidade para gerenciamento de associações. Como um teste de migração, os usuários criados usando a associação sql devem ser capazes de fazer logon e novos usuários devem ser capazes de se registrar. Você pode encontrar o exemplo completo aqui. Consulte também Migrando da Associação de ASP.NET para a Identidade ASP.NET.
Introdução
Criando um aplicativo com associação ao SQL
Precisamos começar com um aplicativo existente que usa a associação sql e tem dados de usuário e função. Para fins deste artigo, vamos criar um aplicativo Web no Visual Studio 2010.
Usando a ferramenta ASP.NET Configuration, crie dois usuários: oldAdminUser e oldUser.
Crie uma função chamada Administração e adicione 'oldAdminUser' como um usuário nessa função.
Crie uma seção Administração do site com um Default.aspx. Defina a marca de autorização no arquivo web.config para habilitar o acesso somente a usuários em funções de Administração. Mais informações podem ser encontradas aqui https://www.asp.net/web-forms/tutorials/security/roles/role-based-authorization-cs
Exiba o banco de dados no Server Explorer para entender as tabelas criadas pelo sistema de associação SQL. Os dados de logon do usuário são armazenados nas tabelas aspnet_Users e aspnet_Membership, enquanto os dados de função são armazenados na tabela aspnet_Roles. Informações sobre quais usuários estão em quais funções são armazenadas na tabela aspnet_UsersInRoles. Para o gerenciamento básico de associação, é suficiente portar as informações nas tabelas acima para o sistema de identidade ASP.NET.
Migrando para Visual Studio 2013
Instale Visual Studio Express 2013 para Web ou Visual Studio 2013 juntamente com as atualizações mais recentes.
Abra o projeto acima na versão instalada do Visual Studio. Se SQL Server Express não estiver instalado no computador, um prompt será exibido quando você abrir o projeto, já que a cadeia de conexão usa o SQL Express. Você pode optar por instalar o SQL Express ou, como alternativa, alterar a cadeia de conexão para LocalDb. Para este artigo, vamos alterá-lo para LocalDb.
Abra web.config e altere a cadeia de conexão de . SQLExpress para (LocalDb)v11.0. Remova 'User Instance=true' da cadeia de conexão.
Abra a Explorer do Servidor e verifique se o esquema e os dados da tabela podem ser observados.
O sistema ASP.NET Identity funciona com a versão 4.5 ou superior da estrutura. Redirecione o aplicativo para 4.5 ou superior.
Compile o projeto para verificar se não há erros.
Instalando os pacotes Nuget
Em Gerenciador de Soluções, clique com o botão direito do mouse no projeto >Gerenciar Pacotes NuGet. Na caixa de pesquisa, insira "Asp.net Identidade". Selecione o pacote na lista de resultados e clique em instalar. Aceite o contrato de licença clicando no botão "Aceito". Observe que esse pacote instalará os pacotes de dependência: EntityFramework e Microsoft ASP.NET Identity Core. Da mesma forma, instale os seguintes pacotes (ignore os últimos 4 pacotes OWIN se você não quiser habilitar o logon do OAuth):
Microsoft.AspNet.Identity.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.Security.Facebook
Microsoft.Owin.Security.Google
Microsoft.Owin.Security.MicrosoftAccount
Microsoft.Owin.Security.Twitter
Migrar banco de dados para o novo sistema de identidade
A próxima etapa é migrar o banco de dados existente para um esquema exigido pelo sistema de identidade ASP.NET. Para isso, executamos um script SQL que tem um conjunto de comandos para criar novas tabelas e migrar informações de usuário existentes para as novas tabelas. O arquivo de script pode ser encontrado aqui.
Esse arquivo de script é específico para este exemplo. Se o esquema das tabelas criadas usando a associação sql for personalizado ou modificado, os scripts precisarão ser alterados adequadamente.
Como gerar o script SQL para migração de esquema
Para que ASP.NET classes de identidade funcionem prontas para uso com os dados dos usuários existentes, precisamos migrar o esquema de banco de dados para aquele necessário para ASP.NET Identity. Podemos fazer isso adicionando novas tabelas e copiando as informações existentes para essas tabelas. Por padrão, ASP.NET Identity usa EntityFramework para mapear as classes de modelo de identidade de volta para o banco de dados para armazenar/recuperar informações. Essas classes de modelo implementam as principais interfaces de identidade que definem objetos de usuário e função. As tabelas e as colunas no banco de dados são baseadas nessas classes de modelo. As classes de modelo EntityFramework em Identity v2.1.0 e suas propriedades são definidas abaixo
IdentityUser | Tipo | IdentityRole | IdentityUserRole | IdentityUserLogin | IdentityUserClaim |
---|---|---|---|---|---|
ID | string | Id | RoleId | ProviderKey | Id |
Nome de Usuário | string | Nome | UserId | UserId | ClaimType |
PasswordHash | string | LoginProvider | ClaimValue | ||
SecurityStamp | string | User_id | |||
string | |||||
EmailConfirmado | bool | ||||
PhoneNumber | string | ||||
PhoneNumberConfirmed | bool | ||||
LockoutEnabled | bool | ||||
LockoutEndDate | Datetime | ||||
AccessFailedCount | INT |
Precisamos ter tabelas para cada um desses modelos com colunas correspondentes às propriedades. O mapeamento entre classes e tabelas é definido no OnModelCreating
método do IdentityDBContext
. Isso é conhecido como o método fluente de configuração da API e mais informações podem ser encontradas aqui. A configuração das classes é conforme mencionado abaixo
Classe | Tabela | Chave primária | Chave estrangeira |
---|---|---|---|
IdentityUser | AspnetUsers | Id | |
IdentityRole | AspnetRoles | Id | |
IdentityUserRole | AspnetUserRole | UserId + RoleId | User_Id-AspnetUsers> RoleId-AspnetRoles> |
IdentityUserLogin | AspnetUserLogins | ProviderKey+UserId + LoginProvider | UserId-AspnetUsers> |
IdentityUserClaim | AspnetUserClaims | Id | User_Id-AspnetUsers> |
Com essas informações, podemos criar instruções SQL para criar novas tabelas. Podemos escrever cada instrução individualmente ou gerar todo o script usando comandos do PowerShell EntityFramework que podemos editar conforme necessário. Para fazer isso, no VS, abra o Console do Gerenciador de Pacotes no menu Exibir ou Ferramentas
- Execute o comando "Enable-Migrations" para habilitar as migrações de EntityFramework.
- Execute o comando "Add-migration initial" que cria o código de instalação inicial para criar o banco de dados em C#/VB.
- A etapa final é executar o comando "Update-Database –Script" que gera o script SQL com base nas classes de modelo.
Não há suporte para alguns comandos se o aplicativo usar o SQLite como seu repositório de dados de identidade. Devido a limitações no mecanismo de banco de dados,
Alter
os comandos geram a seguinte exceção:"System.NotSupportedException: o SQLite não dá suporte a essa operação de migração."
Como alternativa, execute as migrações do Code First no banco de dados para alterar as tabelas.
Esse script de geração de banco de dados pode ser usado como um início em que faremos alterações adicionais para adicionar novas colunas e copiar dados. A vantagem disso é que geramos a _MigrationHistory
tabela que é usada por EntityFramework para modificar o esquema de banco de dados quando as classes de modelo mudam para versões futuras de versões de identidade.
As informações do usuário de associação sql tinham outras propriedades além daquelas na classe de modelo de usuário identidade, ou seja, email, tentativas de senha, data de último logon, data de último bloqueio etc. Essas informações são úteis e gostaríamos que elas fossem transferidas para o sistema de identidade. Isso pode ser feito adicionando propriedades adicionais ao modelo de usuário e mapeando-as de volta para as colunas de tabela no banco de dados. Podemos fazer isso adicionando uma classe que subclasse o IdentityUser
modelo. Podemos adicionar as propriedades a essa classe personalizada e editar o script SQL para adicionar as colunas correspondentes ao criar a tabela. O código dessa classe é descrito mais adiante no artigo. O script SQL para criar a AspnetUsers
tabela depois de adicionar as novas propriedades seria
CREATE TABLE [dbo].[AspNetUsers] (
[Id] NVARCHAR (128) NOT NULL,
[UserName] NVARCHAR (MAX) NULL,
[PasswordHash] NVARCHAR (MAX) NULL,
[SecurityStamp] NVARCHAR (MAX) NULL,
[EmailConfirmed] BIT NOT NULL,
[PhoneNumber] NVARCHAR (MAX) NULL,
[PhoneNumberConfirmed] BIT NOT NULL,
[TwoFactorEnabled] BIT NOT NULL,
[LockoutEndDateUtc] DATETIME NULL,
[LockoutEnabled] BIT NOT NULL,
[AccessFailedCount] INT NOT NULL,
[ApplicationId] UNIQUEIDENTIFIER NOT NULL,
[LegacyPasswordHash] NVARCHAR (MAX) NULL,
[LoweredUserName] NVARCHAR (256) NOT NULL,
[MobileAlias] NVARCHAR (16) DEFAULT (NULL) NULL,
[IsAnonymous] BIT DEFAULT ((0)) NOT NULL,
[LastActivityDate] DATETIME2 NOT NULL,
[MobilePIN] NVARCHAR (16) NULL,
[Email] NVARCHAR (256) NULL,
[LoweredEmail] NVARCHAR (256) NULL,
[PasswordQuestion] NVARCHAR (256) NULL,
[PasswordAnswer] NVARCHAR (128) NULL,
[IsApproved] BIT NOT NULL,
[IsLockedOut] BIT NOT NULL,
[CreateDate] DATETIME2 NOT NULL,
[LastLoginDate] DATETIME2 NOT NULL,
[LastPasswordChangedDate] DATETIME2 NOT NULL,
[LastLockoutDate] DATETIME2 NOT NULL,
[FailedPasswordAttemptCount] INT NOT NULL,
[FailedPasswordAttemptWindowStart] DATETIME2 NOT NULL,
[FailedPasswordAnswerAttemptCount] INT NOT NULL,
[FailedPasswordAnswerAttemptWindowStart] DATETIME2 NOT NULL,
[Comment] NTEXT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC),
FOREIGN KEY ([ApplicationId]) REFERENCES [dbo].[aspnet_Applications] ([ApplicationId]),
);
Em seguida, precisamos copiar as informações existentes do banco de dados de associação sql para as tabelas recém-adicionadas para Identidade. Isso pode ser feito por meio do SQL copiando dados diretamente de uma tabela para outra. Para adicionar dados às linhas da tabela, usamos o INSERT INTO [Table]
constructo . Para copiar de outra tabela, podemos usar a INSERT INTO
instrução junto com a SELECT
instrução . Para obter todas as informações do usuário, precisamos consultar as tabelas aspnet_Users e aspnet_Membership e copiar os dados para a tabela AspNetUsers . Usamos as INSERT INTO
instruções e SELECT
junto com JOIN
e LEFT OUTER JOIN
. Para obter mais informações sobre como consultar e copiar dados entre tabelas, consulte este link. Além disso, as tabelas AspnetUserLogins e AspnetUserClaims estão vazias para começar, pois não há informações na associação sql mapeadas para isso por padrão. As únicas informações copiadas são para usuários e funções. Para o projeto criado nas etapas anteriores, a consulta SQL para copiar informações para a tabela de usuários seria
INSERT INTO AspNetUsers(Id,UserName,PasswordHash,SecurityStamp,EmailConfirmed,
PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,
ApplicationId,LoweredUserName,MobileAlias,IsAnonymous,LastActivityDate,LegacyPasswordHash,
MobilePIN,Email,LoweredEmail,PasswordQuestion,PasswordAnswer,IsApproved,IsLockedOut,CreateDate,
LastLoginDate,LastPasswordChangedDate,LastLockoutDate,FailedPasswordAttemptCount,
FailedPasswordAnswerAttemptWindowStart,FailedPasswordAnswerAttemptCount,FailedPasswordAttemptWindowStart,Comment)
SELECT aspnet_Users.UserId,aspnet_Users.UserName,(aspnet_Membership.Password+'|'+CAST(aspnet_Membership.PasswordFormat as varchar)+'|'+aspnet_Membership.PasswordSalt),NewID(),
'true',NULL,'false','true',aspnet_Membership.LastLockoutDate,'true','0',
aspnet_Users.ApplicationId,aspnet_Users.LoweredUserName,
aspnet_Users.MobileAlias,aspnet_Users.IsAnonymous,aspnet_Users.LastActivityDate,aspnet_Membership.Password,
aspnet_Membership.MobilePIN,aspnet_Membership.Email,aspnet_Membership.LoweredEmail,aspnet_Membership.PasswordQuestion,aspnet_Membership.PasswordAnswer,
aspnet_Membership.IsApproved,aspnet_Membership.IsLockedOut,aspnet_Membership.CreateDate,aspnet_Membership.LastLoginDate,aspnet_Membership.LastPasswordChangedDate,
aspnet_Membership.LastLockoutDate,aspnet_Membership.FailedPasswordAttemptCount, aspnet_Membership.FailedPasswordAnswerAttemptWindowStart,
aspnet_Membership.FailedPasswordAnswerAttemptCount,aspnet_Membership.FailedPasswordAttemptWindowStart,aspnet_Membership.Comment
FROM aspnet_Users
LEFT OUTER JOIN aspnet_Membership ON aspnet_Membership.ApplicationId = aspnet_Users.ApplicationId
AND aspnet_Users.UserId = aspnet_Membership.UserId;
Na instrução SQL acima, as informações sobre cada usuário das tabelas aspnet_Users e aspnet_Membership são copiadas para as colunas da tabela AspnetUsers . A única modificação feita aqui é quando copiamos a senha. Como o algoritmo de criptografia para senhas na associação ao SQL usou 'PasswordSalt' e 'PasswordFormat', copiamos isso também junto com a senha de hash para que ela possa ser usada para descriptografar a senha pelo Identity. Isso é explicado mais adiante no artigo ao conectar um hasher de senha personalizado.
Esse arquivo de script é específico para este exemplo. Para aplicativos que têm tabelas adicionais, os desenvolvedores podem seguir uma abordagem semelhante para adicionar propriedades adicionais na classe de modelo de usuário e mapeá-las para colunas na tabela AspnetUsers. Para executar o script,
Abra o Gerenciador de Servidores. Expanda a conexão 'ApplicationServices' para exibir as tabelas. Clique com o botão direito do mouse no nó Tabelas e selecione a opção 'Nova Consulta'
Na janela de consulta, copie e cole todo o script SQL do arquivo Migrations.sql. Execute o arquivo de script clicando no botão de seta "Executar".
Atualize a janela Explorer do Servidor. Cinco novas tabelas são criadas no banco de dados.
Veja abaixo como as informações nas tabelas de associação do SQL são mapeadas para o novo sistema de identidade.
aspnet_Roles -> AspNetRoles
asp_netUsers e asp_netMembership –> AspNetUsers
aspnet_UserInRoles –> AspNetUserRoles
Conforme explicado na seção acima, as tabelas AspNetUserClaims e AspNetUserLogins estão vazias. O campo 'Discriminatório' na tabela AspNetUser deve corresponder ao nome da classe de modelo definido como uma próxima etapa. Além disso, a coluna PasswordHash está no formato 'senha criptografada |senha salt|formato de senha'. Isso permite que você use uma lógica de criptografia de associação sql especial para que você possa reutilizar senhas antigas. Isso é explicado posteriormente no artigo.
Criando modelos e páginas de associação
Conforme mencionado anteriormente, o recurso Identidade usa o Entity Framework para conversar com o banco de dados para armazenar informações de conta por padrão. Para trabalhar com dados existentes na tabela, precisamos criar classes de modelo que mapeiem de volta para as tabelas e as conectem no sistema de identidade. Como parte do contrato de identidade, as classes de modelo devem implementar as interfaces definidas na dll Identity.Core ou podem estender a implementação existente dessas interfaces disponíveis em Microsoft.AspNet.Identity.EntityFramework.
Em nosso exemplo, as tabelas AspNetRoles, AspNetUserClaims, AspNetLogins e AspNetUserRole têm colunas semelhantes à implementação existente do sistema de identidade. Portanto, podemos reutilizar as classes existentes para mapear para essas tabelas. A tabela AspNetUser tem algumas colunas adicionais que são usadas para armazenar informações adicionais das tabelas de associação do SQL. Isso pode ser mapeado criando uma classe de modelo que estende a implementação existente de 'IdentityUser' e adiciona as propriedades adicionais.
Crie uma pasta Modelos no projeto e adicione uma classe Usuário. O nome da classe deve corresponder aos dados adicionados na coluna 'Discriminatório' da tabela 'AspnetUsers'.
A classe User deve estender a classe IdentityUser encontrada na dll Microsoft.AspNet.Identity.EntityFramework . Declare as propriedades na classe que são mapeadas de volta para as colunas AspNetUser. As propriedades ID, Nome de usuário, PasswordHash e SecurityStamp são definidas no IdentityUser e, portanto, são omitidas. Abaixo está o código da classe User que tem todas as propriedades
public class User : IdentityUser { public User() { CreateDate = DateTime.Now; IsApproved = false; LastLoginDate = DateTime.Now; LastActivityDate = DateTime.Now; LastPasswordChangedDate = DateTime.Now; LastLockoutDate = DateTime.Parse("1/1/1754"); FailedPasswordAnswerAttemptWindowStart = DateTime.Parse("1/1/1754"); FailedPasswordAttemptWindowStart = DateTime.Parse("1/1/1754"); } public System.Guid ApplicationId { get; set; } public string MobileAlias { get; set; } public bool IsAnonymous { get; set; } public System.DateTime LastActivityDate { get; set; } public string MobilePIN { get; set; } public string LoweredEmail { get; set; } public string LoweredUserName { get; set; } public string PasswordQuestion { get; set; } public string PasswordAnswer { get; set; } public bool IsApproved { get; set; } public bool IsLockedOut { get; set; } public System.DateTime CreateDate { get; set; } public System.DateTime LastLoginDate { get; set; } public System.DateTime LastPasswordChangedDate { get; set; } public System.DateTime LastLockoutDate { get; set; } public int FailedPasswordAttemptCount { get; set; } public System.DateTime FailedPasswordAttemptWindowStart { get; set; } public int FailedPasswordAnswerAttemptCount { get; set; } public System.DateTime FailedPasswordAnswerAttemptWindowStart { get; set; } public string Comment { get; set; } }
Uma classe Entity Framework DbContext é necessária para persistir dados em modelos de volta às tabelas e recuperar dados de tabelas para preencher os modelos. A dll Microsoft.AspNet.Identity.EntityFramework define a classe IdentityDbContext que interage com as tabelas De identidade para recuperar e armazenar informações. O tuser> IdentityDbContext<usa uma classe 'TUser', que pode ser qualquer classe que estenda a classe IdentityUser.
Crie uma nova classe ApplicationDBContext que estende IdentityDbContext na pasta 'Models', passando a classe 'User' criada na etapa 1
public class ApplicationDbContext : IdentityDbContext<User> { }
O gerenciamento de usuários no novo sistema de identidade é feito usando a classe tuser> UserManager<definida na dll Microsoft.AspNet.Identity.EntityFramework. Precisamos criar uma classe personalizada que estenda UserManager, passando a classe 'User' criada na etapa 1.
Na pasta Modelos, crie uma nova classe UserManager que estenda o usuário UserManager<>
public class UserManager : UserManager<User> { }
As senhas dos usuários do aplicativo são criptografadas e armazenadas no banco de dados. O algoritmo de criptografia usado na associação sql é diferente do do novo sistema de identidade. Para reutilizar senhas antigas, precisamos descriptografar seletivamente senhas quando usuários antigos fizerem logon usando o algoritmo de associações sql ao usar o algoritmo de criptografia em Identidade para os novos usuários.
A classe UserManager tem uma propriedade 'PasswordHasher' que armazena uma instância de uma classe que implementa a interface 'IPasswordHasher'. Isso é usado para criptografar/descriptografar senhas durante transações de autenticação de usuário. Na classe UserManager definida na etapa 3, crie uma nova classe SQLPasswordHasher e copie o código abaixo.
public class SQLPasswordHasher : PasswordHasher { public override string HashPassword(string password) { return base.HashPassword(password); } public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) { string[] passwordProperties = hashedPassword.Split('|'); if (passwordProperties.Length != 3) { return base.VerifyHashedPassword(hashedPassword, providedPassword); } else { string passwordHash = passwordProperties[0]; int passwordformat = 1; string salt = passwordProperties[2]; if (String.Equals(EncryptPassword(providedPassword, passwordformat, salt), passwordHash, StringComparison.CurrentCultureIgnoreCase)) { return PasswordVerificationResult.SuccessRehashNeeded; } else { return PasswordVerificationResult.Failed; } } } //This is copied from the existing SQL providers and is provided only for back-compat. private string EncryptPassword(string pass, int passwordFormat, string salt) { if (passwordFormat == 0) // MembershipPasswordFormat.Clear return pass; byte[] bIn = Encoding.Unicode.GetBytes(pass); byte[] bSalt = Convert.FromBase64String(salt); byte[] bRet = null; if (passwordFormat == 1) { // MembershipPasswordFormat.Hashed HashAlgorithm hm = HashAlgorithm.Create("SHA1"); if (hm is KeyedHashAlgorithm) { KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm; if (kha.Key.Length == bSalt.Length) { kha.Key = bSalt; } else if (kha.Key.Length < bSalt.Length) { byte[] bKey = new byte[kha.Key.Length]; Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length); kha.Key = bKey; } else { byte[] bKey = new byte[kha.Key.Length]; for (int iter = 0; iter < bKey.Length; ) { int len = Math.Min(bSalt.Length, bKey.Length - iter); Buffer.BlockCopy(bSalt, 0, bKey, iter, len); iter += len; } kha.Key = bKey; } bRet = kha.ComputeHash(bIn); } else { byte[] bAll = new byte[bSalt.Length + bIn.Length]; Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length); Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); bRet = hm.ComputeHash(bAll); } } return Convert.ToBase64String(bRet); }
Resolva os erros de compilação importando os namespaces System.Text e System.Security.Cryptography.
O método EncodePassword criptografa a senha de acordo com a implementação de criptografia de associação sql padrão. Isso é obtido da dll System.Web. Se o aplicativo antigo usou uma implementação personalizada, ele deverá ser refletido aqui. Precisamos definir dois outros métodos HashPassword e VerifyHashedPassword que usam o método EncodePassword para hash de uma determinada senha ou verificar uma senha de texto sem formatação com a existente no banco de dados.
O sistema de associação sql usou PasswordHash, PasswordSalt e PasswordFormat para hash da senha inserida pelos usuários quando eles registram ou alteram sua senha. Durante a migração, todos os três campos são armazenados na coluna PasswordHash na tabela AspNetUser separada pelo caractere '|'. Quando um usuário faz logon e a senha tem esses campos, usamos a criptografia de associação sql para marcar a senha; caso contrário, usamos a criptografia padrão do sistema de identidade para verificar a senha. Dessa forma, os usuários antigos não precisarão alterar suas senhas depois que o aplicativo for migrado.
Declare o construtor para a classe UserManager e passe-o como SQLPasswordHasher para a propriedade no construtor.
public UserManager() : base(new UserStore<User>(new ApplicationDbContext())) { this.PasswordHasher = new SQLPasswordHasher(); }
Criar novas páginas de gerenciamento de conta
A próxima etapa na migração é adicionar páginas de gerenciamento de conta que permitirão que um usuário se registre e faça logon. As páginas de conta antigas da associação ao SQL usam controles que não funcionam com o novo sistema de identidade. Para adicionar as novas páginas de gerenciamento de usuários, siga o tutorial neste link https://www.asp.net/identity/overview/getting-started/adding-aspnet-identity-to-an-empty-or-existing-web-forms-project a partir da etapa "Adicionando Web Forms para registrar usuários em seu aplicativo", pois já criamos o projeto e adicionamos os pacotes NuGet.
Precisamos fazer algumas alterações para que o exemplo funcione com o projeto que temos aqui.
O código Register.aspx.cs e Login.aspx.cs por trás das classes usa o
UserManager
dos pacotes de identidade para criar um Usuário. Para este exemplo, use o UserManager adicionado na pasta Modelos seguindo as etapas mencionadas anteriormente.Use a classe User criada em vez do IdentityUser em Register.aspx.cs e o código Login.aspx.cs por trás das classes. Isso conecta nossa classe de usuário personalizada ao sistema de identidade.
A parte para criar o banco de dados pode ser ignorada.
O desenvolvedor precisa definir a ApplicationId para que o novo usuário corresponda à ID do aplicativo atual. Isso pode ser feito consultando o ApplicationId para este aplicativo antes que um objeto de usuário seja criado na classe Register.aspx.cs e definindo-o antes de criar um usuário.
Exemplo:
Definir um método na página Register.aspx.cs para consultar a tabela aspnet_Applications e obter a ID do aplicativo de acordo com o nome do aplicativo
private Guid GetApplicationID() { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString)) { string queryString = "SELECT ApplicationId from aspnet_Applications WHERE ApplicationName = '/'"; //Set application name as in database SqlCommand command = new SqlCommand(queryString, connection); command.Connection.Open(); var reader = command.ExecuteReader(); while (reader.Read()) { return reader.GetGuid(0); } return Guid.NewGuid(); } }
Agora, defina isso no objeto de usuário
var currentApplicationId = GetApplicationID(); User user = new User() { UserName = Username.Text, ApplicationId=currentApplicationId, …};
Use o nome de usuário e a senha antigos para fazer logon em um usuário existente. Use a página Registrar para criar um novo usuário. Verifique também se os usuários estão em funções conforme o esperado.
A portabilidade para o sistema de identidade ajuda o usuário a adicionar a Autenticação Aberta (OAuth) ao aplicativo. Consulte o exemplo aqui que tem o OAuth habilitado.
Próximas etapas
Neste tutorial, mostramos como portar usuários da associação do SQL ao ASP.NET Identity, mas não portamos dados de perfil. No próximo tutorial, examinaremos a portabilidade de dados de perfil da associação do SQL para o novo sistema de identidade.
Você pode deixar comentários na parte inferior deste artigo.
Obrigado a Tom Dykstra e Rick Anderson por revisarem o artigo.