ASP.NET 멤버 자격 인증에서 ASP.NET Core 2.0 Identity로 마이그레이션
작성자: Isaac Levin
이 문서에서는 멤버 자격 인증을 사용하여 ASP.NET 앱의 데이터베이스 스키마를 ASP.NET Core 2.0 Identity로 마이그레이션하는 방법을 보여 줍니다.
참고 항목
이 문서에서는 ASP.NET 멤버 자격 기반 앱의 데이터베이스 스키마를 ASP.NET Core Identity에 사용되는 데이터베이스 스키마로 마이그레이션하는 데 필요한 단계를 제공합니다. ASP.NET 멤버 자격 기반 인증에서 ASP.NET Identity로 마이그레이션하는 자세한 내용은 기존 앱을 SQL 멤버 자격에서 ASP.NET Identity로 마이그레이션을 참조하세요. ASP.NET Core Identity에 대한 자세한 내용은 ASP.NET Core의 Identity 소개를 참조하세요.
멤버 자격 스키마 검토
ASP.NET 2.0 이전에는 개발자가 앱에 대한 전체 인증 및 권한 부여 프로세스를 만들어야 했습니다. ASP.NET 2.0에서는 멤버 자격이 도입되어 ASP.NET 앱 내에서 보안을 처리하는 상용구 솔루션을 제공합니다. 이제 개발자는 ASP.NET SQL Server 등록 도구(Aspnet_regsql.exe
)(더 이상 지원되지 않음)를 사용하여 스키마를 SQL Server 데이터베이스로 부트스트랩할 수 있었습니다. 이 명령을 실행한 후 데이터베이스에 다음 테이블이 생성되었습니다.
기존 앱을 ASP.NET Core 2.0 Identity로 마이그레이션하려면 이러한 테이블의 데이터를 새 Identity 스키마에서 사용하는 테이블로 마이그레이션해야 합니다.
ASP.NET Core Identity 2.0 스키마
ASP.NET Core 2.0은 ASP.NET 4.5에 도입된 Identity 원칙을 따릅니다. 원칙은 공유되지만 프레임워크 간의 구현은 ASP.NET Core 버전 간에도 다릅니다(ASP.NET Core 2.0으로 인증 및 Identity 마이그레이션 참조).
ASP.NET Core 2.0 Identity에 대한 스키마를 보는 가장 빠른 방법은 새 ASP.NET Core 2.0 앱을 만드는 것입니다. Visual Studio 2017에서 다음 단계를 수행합니다.
파일>새>프로젝트를 선택합니다.
CoreIdentitySample이라는 새 ASP.NET Core 웹 애플리케이션 프로젝트를 만듭니다.
드롭다운에서 ASP.NET Core 2.0을 선택한 다음, 웹 애플리케이션을 선택합니다. 이 템플릿은 Razor Pages 앱을 생성합니다. 확인을 클릭하기 전에 인증 변경을 클릭합니다.
Identity 템플릿에 대한 개별 사용자 계정을 선택합니다. 마지막으로 확인을 클릭한 다음, 확인을 클릭합니다. Visual Studio에서 ASP.NET Core Identity 템플릿을 사용하여 프로젝트를 만듭니다.
도구>NuGet 패키지 관리자>패키지 관리자 콘솔을 선택하여 PMC(패키지 관리자 콘솔) 창을 엽니다.
PMC에서 프로젝트 루트로 이동하고 EF(Entity Framework) Core
Update-Database
명령을 실행합니다.ASP.NET Core 2.0 Identity에서는 EF Core를 사용하여 인증 데이터를 저장하는 데이터베이스와 상호 작용합니다. 새로 만든 앱이 작동하려면 이 데이터를 저장할 데이터베이스가 있어야 합니다. 새 앱을 만든 후 데이터베이스 환경에서 스키마를 검사하는 가장 빠른 방법은 EF Core 마이그레이션을 사용하여 데이터베이스를 만드는 것입니다. 이 프로세스는 로컬 또는 다른 곳에서 해당 스키마를 모방하는 데이터베이스를 만듭니다. 자세한 내용은 이전 설명서를 검토하세요.
EF Core 명령은
appsettings.json
에 지정된 데이터베이스에 대한 연결 문자열을 사용합니다. 다음 연결 문자열 asp-net-coreidentity-라는 localhost의 데이터베이스를 대상으로 합니다. 이 설정에서 EF Core는DefaultConnection
연결 문자열을 사용하도록 구성됩니다.{ "ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=aspnet-core-identity;Trusted_Connection=True;MultipleActiveResultSets=true" } }
Warning
이 문서에서는 연결 문자열 사용을 보여 줍니다. 로컬 데이터베이스를 사용하면 사용자를 인증할 필요가 없지만 프로덕션 환경에서는 연결 문자열 인증할 암호를 포함하는 경우가 있습니다. ROPC(리소스 소유자 암호 자격 증명)는 프로덕션 데이터베이스에서 피해야 하는 보안 위험입니다. 프로덕션 앱은 사용 가능한 가장 안전한 인증 흐름을 사용해야 합니다. 테스트 또는 프로덕션 환경에 배포된 앱의 인증에 대한 자세한 내용은 보안 인증 흐름을 참조 하세요.
보기>SQL Server 개체 탐색기를 선택합니다.
appsettings.json
의ConnectionStrings:DefaultConnection
속성에 지정된 데이터베이스 이름에 해당하는 노드를 확장합니다.Update-Database
명령은 스키마 및 앱 초기화에 필요한 모든 데이터로 지정된 데이터베이스를 만들었습니다. 다음 이미지는 이전 단계를 통해 만든 테이블 구조를 설명합니다.
스키마 마이그레이션
멤버 자격 및 ASP.NET Core Identity에 대한 테이블 구조와 필드에는 미묘한 차이가 있습니다. ASP.NET 및 ASP.NET Core 앱의 인증/권한 부여에 대한 패턴이 크게 변경되었습니다. 여전히 Identity와 함께 사용되는 주요 개체는 사용자 및 역할입니다. 다음은 사용자, 역할 및 UserRoles에 대한 매핑 테이블입니다.
사용자
Identity ( dbo.AspNetUsers ) 열 |
Type | 멤버 자격 ( dbo.aspnet_Users / dbo.aspnet_Membership ) 열 |
Type |
---|---|---|---|
Id |
string |
aspnet_Users.UserId |
string |
UserName |
string |
aspnet_Users.UserName |
string |
Email |
string |
aspnet_Membership.Email |
string |
NormalizedUserName |
string |
aspnet_Users.LoweredUserName |
string |
NormalizedEmail |
string |
aspnet_Membership.LoweredEmail |
string |
PhoneNumber |
string |
aspnet_Users.MobileAlias |
string |
LockoutEnabled |
bit |
aspnet_Membership.IsLockedOut |
bit |
IsLockedOut
에 매핑 LockoutEnabled
되지 않습니다. IsLockedOut
는 사용자가 실패한 로그인이 너무 많고 설정된 시간 동안 잠긴 경우 설정됩니다. LockoutEnabled
을 사용하면 로그인 시도가 너무 많은 사용자를 잠글 수 있습니다. 사용자가 실패한 로그인 시도가 LockoutEnd
너무 많으면 나중에 날짜로 설정되며 사용자는 해당 날짜까지 로그인할 수 없습니다. false이면 LockoutEnabled
사용자가 너무 많은 로그인 실패 시도에 대해 잠기지 않습니다. OWASP당 몇 번의 실패한 시도 후 임시 계정 잠금은 합법적인 사용자에 대한 DoS 공격의 대상이 너무 간단합니다.
잠금에 대한 자세한 내용은 약한 잠금 메커니즘에 대한 OWASP 테스트를 참조 하세요.
실패한 로그인 잠금을 Identity 사용하도록 설정하려는 앱으로 마이그레이션하는 앱은 마이그레이션의 일부로 true로 설정 LockoutEnabled
되어야 합니다.
참고 항목
모든 필드 매핑이 멤버 자격에서 ASP.NET Core Identity로의 일대일 관계와 유사하지는 않습니다. 위의 표는 기본 멤버 자격 사용자 스키마를 사용하여 ASP.NET Core Identity 스키마에 매핑합니다. 멤버 자격에 사용된 다른 사용자 지정 필드는 수동으로 매핑되어야 합니다. 이 매핑에는 암호 기준과 암호 솔트 둘 다 간에 마이그레이션되지 않기 때문에 암호에 대한 맵이 없습니다. 암호를 Null로 두고 사용자에게 암호를 재설정하도록 요청하는 것이 좋습니다. ASP.NET Core Identity에서는 사용자가 잠겨 있는 경우 나중에 LockoutEnd
를 날짜로 설정해야 합니다. 마이그레이션 스크립트에 표시됩니다.
Roles
Identity ( dbo.AspNetRoles ) 열 |
Type | 멤버 자격 ( dbo.aspnet_Roles ) 열 |
Type |
---|---|---|---|
Id |
string |
RoleId |
string |
Name |
string |
RoleName |
string |
NormalizedName |
string |
LoweredRoleName |
string |
사용자 역할
Identity ( dbo.AspNetUserRoles ) 열 |
Type | 멤버 자격 ( dbo.aspnet_UsersInRoles ) 열 |
Type |
---|---|---|---|
RoleId |
string |
RoleId |
string |
UserId |
string |
UserId |
string |
사용자 및 역할에 대한 마이그레이션 스크립트를 만들 때 위의 매핑 테이블을 참조합니다. 다음 예제에서는 데이터베이스 서버에 두 개의 데이터베이스가 있다고 가정합니다. 하나의 데이터베이스에는 기존 ASP.NET 멤버 자격 스키마 및 데이터가 포함됩니다. 다른 CoreIdentitySample 데이터베이스는 앞에서 설명한 단계를 사용하여 만들어졌습니다. 자세한 내용을 위해 주석이 인라인으로 포함됩니다.
-- THIS SCRIPT NEEDS TO RUN FROM THE CONTEXT OF THE MEMBERSHIP DB
BEGIN TRANSACTION MigrateUsersAndRoles
USE aspnetdb
-- INSERT USERS
INSERT INTO CoreIdentitySample.dbo.AspNetUsers
(Id,
UserName,
NormalizedUserName,
PasswordHash,
SecurityStamp,
EmailConfirmed,
PhoneNumber,
PhoneNumberConfirmed,
TwoFactorEnabled,
LockoutEnd,
LockoutEnabled,
AccessFailedCount,
Email,
NormalizedEmail)
SELECT aspnet_Users.UserId,
aspnet_Users.UserName,
-- The NormalizedUserName value is upper case in ASP.NET Core Identity
UPPER(aspnet_Users.UserName),
-- Creates an empty password since passwords don't map between the 2 schemas
'',
/*
The SecurityStamp token is used to verify the state of an account and
is subject to change at any time. It should be initialized as a new ID.
*/
NewID(),
/*
EmailConfirmed is set when a new user is created and confirmed via email.
Users must have this set during migration to reset passwords.
*/
1,
aspnet_Users.MobileAlias,
CASE
WHEN aspnet_Users.MobileAlias IS NULL THEN 0
ELSE 1
END,
-- 2FA likely wasn't setup in Membership for users, so setting as false.
0,
CASE
-- Setting lockout date to time in the future (1,000 years)
WHEN aspnet_Membership.IsLockedOut = 1 THEN Dateadd(year, 1000,
Sysutcdatetime())
ELSE NULL
END,
aspnet_Membership.IsLockedOut,
/*
AccessFailedAccount is used to track failed logins. This is stored in
Membership in multiple columns. Setting to 0 arbitrarily.
*/
0,
aspnet_Membership.Email,
-- The NormalizedEmail value is upper case in ASP.NET Core Identity
UPPER(aspnet_Membership.Email)
FROM aspnet_Users
LEFT OUTER JOIN aspnet_Membership
ON aspnet_Membership.ApplicationId =
aspnet_Users.ApplicationId
AND aspnet_Users.UserId = aspnet_Membership.UserId
LEFT OUTER JOIN CoreIdentitySample.dbo.AspNetUsers
ON aspnet_Membership.UserId = AspNetUsers.Id
WHERE AspNetUsers.Id IS NULL
-- INSERT ROLES
INSERT INTO CoreIdentitySample.dbo.AspNetRoles(Id, Name)
SELECT RoleId, RoleName
FROM aspnet_Roles;
-- INSERT USER ROLES
INSERT INTO CoreIdentitySample.dbo.AspNetUserRoles(UserId, RoleId)
SELECT UserId, RoleId
FROM aspnet_UsersInRoles;
IF @@ERROR <> 0
BEGIN
ROLLBACK TRANSACTION MigrateUsersAndRoles
RETURN
END
COMMIT TRANSACTION MigrateUsersAndRoles
이전 스크립트가 완료되면 이전에 만든 ASP.NET Core Identity 앱이 멤버 자격 사용자로 채워집니다. 사용자는 로그인하기 전에 암호를 변경해야 합니다.
참고 항목
멤버 자격 시스템에 이메일 주소와 일치하지 않는 사용자 이름이 있는 사용자가 있는 경우 이를 수용하기 위해 이전에 만든 앱에 대한 변경이 필요합니다. 기본 템플릿에는 UserName
및 Email
이 같을 것으로 예상됩니다. 서로 다른 경우 Email
대신 UserName
을 사용하도록 로그인 프로세스를 수정해야 합니다.
PageModel
로그인 페이지의 에 있는 전자 메일 속성에서 특성을 제거 [EmailAddress]
합니다. 이름을 UserName으로 바꿉니다. 이를 위해서는 View 및 PageModel에서 EmailAddress
가 언급된 모든 위치를 변경해야 합니다. 결과는 다음과 같습니다.
다음 단계
이 자습서에서는 사용자를 SQL 멤버 자격에서 ASP.NET Core 2.0 Identity로 이동하는 방법을 배웠습니다. ASP.NET Core Identity에 대한 자세한 내용은 Identity 소개를 참조하세요.
ASP.NET Core