연습 - ID 지원 구성

완료됨

ID는 사용자 지정 없이 기본적으로 작동합니다. 이 단원에서는 ID가 기존 ASP.NET Core Razor Pages 프로젝트에 추가됩니다.

시작 프로젝트 열기

권장되는 GitHub Codespace를 사용하려면 MicrosoftDocs/mslearn-secure-aspnet-core-identity 리포지토리의 Codespaces로 이동합니다. 분기를 사용하여 새 Codespace를 main 만든 다음 앱 탐색으로 건너뜁니다.

로컬 Dev Container를 사용하려면 다음 단계를 따릅니다.

  1. Visual Studio Code 창에서 F1 키를 눌러 명령 팔레트를 엽니다. Dev-Containers: 컨테이너 볼륨에서 리포지토리 복제...를 검색하여 선택합니다.

  2. 다음 리포지토리 URL https://github.com/MicrosoftDocs/mslearn-secure-aspnet-core-identity을 입력합니다. 분기를 main 선택합니다. Visual Studio Code는 개발 컨테이너를 만듭니다. 권장 확장을 설치하라는 프롬프트를 수락합니다.

  3. 앱 탐색으로 건너뜁니다.

로컬 개발 환경을 사용하려면 다음 단계를 따릅니다.

  1. 터미널 창에서 다음 명령을 실행하여 시작 프로젝트를 가져옵니다.

    git clone https://github.com/MicrosoftDocs/mslearn-secure-aspnet-core-identity
    
  2. 소스 코드 디렉터리로 전환하고 Visual Studio Code를 시작합니다.

    cd mslearn-secure-aspnet-core-identity
    code .
    

    Visual Studio Code를 엽니다. 권장 확장을 설치하라는 프롬프트는 수락하지만, 컨테이너에서 다시 열기 메시지가 표시되는 경우 이를 선택하지 마세요. 다음 단계를 계속합니다.

앱 살펴보기

  1. 프로젝트가 로드된 후 Ctrl+Shift+`를 눌러 새 터미널 창을 엽니다.

  2. 새 터미널 창에서 위치를 RazorPagesPizza 디렉터리로 설정합니다.

    cd RazorPagesPizza
    
  3. 탐색기 창에서 RazorPagesPizza 디렉터리를 확장하여 코드를 봅니다. RazorPagesPizza는 프로젝트 디렉터리입니다. 계속 진행하면서 이 모듈에서 설명하는 모든 경로가 이 위치를 기준으로 하는 것으로 가정합니다.

    앱을 실행하여 빠른 소개를 살펴보겠습니다.

  4. 터미널 창에서 프로젝트를 빌드하고 앱을 실행합니다.

    dotnet run
    
  5. 터미널 출력에 표시되는 URL을 기록해 둡니다. 예들 들어 https://localhost:7192입니다.

  6. Ctrl+click을 사용하여 URL을 선택하여 브라우저에서 앱을 엽니다.

    Important

    로컬 Docker에서 Dev Container를 사용하는 경우 컨테이너 내부의 SSL 인증서는 브라우저에서 신뢰받지 못합니다. 웹앱을 보려면 다음 중 하나를 수행해야 합니다.

    • 인증서 오류를 무시합니다. Microsoft Edge를 사용하는 경우 고급을 선택하고 localhost로 계속합니다(권장되지 않음). 세부 정보는 브라우저에 따라 다릅니다.
    • 인증서를 저장하고 신뢰할 수 있는 인증 기관에 추가합니다.
    • 컨테이너 내에서 기존 개발 인증서를 가져옵니다. 자세한 내용은 ./devcontainer/devcontainter.json에서 생성된 주석을 참조하세요.
  7. 브라우저에서 웹앱을 탐색합니다. 헤더의 링크 사용:

    1. 피자 목록으로 이동

    인증은 필요 없습니다.

  8. 앱을 중지하려면 터미널 창에서 Ctrl+C를 누릅니다.

프로젝트에 ASP.NET Core ID 추가

dotnet 명령줄 도구를 사용하여 기본 ID 구현을 추가할 수 있습니다.

  1. 다음과 같이 ASP.NET Core 코드 스캐폴더를 설치합니다.

    dotnet tool install dotnet-aspnet-codegenerator --version 8.0.* --global
    

    스캐폴더는 다음과 같은 .NET 도구입니다.

    • 프로젝트에 기본 ID 구성 요소를 추가하는 데 사용됩니다.
    • 다음 단원에서 ID UI 구성 요소를 사용자 지정할 수 있습니다.
    • 이 모듈에서 dotnet aspnet-codegenerator를 통해 호출됩니다.
  2. 다음 NuGet 패키지를 프로젝트에 추가합니다.

    dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 8.0.*
    dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore --version 8.0.*
    dotnet add package Microsoft.AspNetCore.Identity.UI --version 8.0.*
    dotnet add package Microsoft.EntityFrameworkCore.Design --version 8.0.*
    dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 8.0.*
    dotnet add package Microsoft.EntityFrameworkCore.Tools --version 8.0.*
    

    이 패키지는 스캐폴더에서 사용하는 코드 생성 템플릿 및 종속성을 설치합니다.

    사용 가능한 생성기를 보려면 다음을 수행합니다.

    • 명령 셸에서 dotnet aspnet-codegenerator -h를 실행합니다.
    • Visual Studio의 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가>스캐폴드 항목 새로 만들기를 선택합니다.
  3. 스캐폴더를 사용하여 프로젝트에 기본 ID 구성 요소를 추가합니다. 터미널에서 다음 명령을 실행합니다.

    dotnet aspnet-codegenerator identity --useDefaultUI --dbContext RazorPagesPizzaAuth --userClass RazorPagesPizzaUser
    

    이전 명령에서 다음을 확인할 수 있습니다.

    • identity로 파악된 생성기는 ID 프레임워크를 프로젝트에 추가하는 데 사용됩니다.
    • --useDefaultUI 옵션은 기본 UI 요소를 포함하는 RCL(Razor 클래스 라이브러리)이 사용됨을 나타냅니다. 부트스트랩이 구성 요소의 스타일을 지정하는 데 사용됩니다.
    • 생성할 EF Core 데이터베이스 컨텍스트 클래스의 이름을 지정하는 --dbContext 옵션
    • --userClass 옵션은 생성할 사용자 클래스의 이름을 지정합니다. 기본 사용자 클래스는 IdentityUser사용자 클래스가 이후 단원에서 확장되므로 명명 RazorPagesPizzaUser 된 사용자 지정 사용자 클래스가 지정됩니다. RazorPagesPizzaUser 클래스는 IdentityUser에서 파생됩니다.

    RazorPagesPizza 디렉터리에 표시되는 Areas 디렉터리 구조는 다음과 같습니다.

    • Areas
      • Identity(영역과 동일한 줄에 표시됨)
        • Data
          • RazorPagesPizzaAuth.cs
          • RazorPagesPizzaUser.cs
        • Pages
          • _ValidationScriptsPartial.cshtml
          • _ViewStart.cshtml

    Areas 디렉터리가 탐색기 창에 자동으로 표시되지 않으면 탐색기 창의 MSLEARN-SECURE-ASPNET-CORE-IDENTITY 헤더에서 탐색기 새로 고침 단추를 선택합니다.

    Areas는 ASP.NET Core 웹앱을 좀 더 작은 기능 그룹으로 분할하는 방법을 제공합니다.

    또한 스캐폴더는 아래에 강조 표시된 대로 Program.cs를 변경했습니다(가독성을 위해 다시 서식 지정됨).

    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using RazorPagesPizza.Areas.Identity.Data;
    var builder = WebApplication.CreateBuilder(args);
    var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection") 
        ?? throw new InvalidOperationException("Connection string 'RazorPagesPizzaAuthConnection' not found.");
    
    builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString));
    
    builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<RazorPagesPizzaAuth>();
    
    // Add services to the container.
    builder.Services.AddRazorPages();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapRazorPages();
    
    app.Run();
    

    위의 코드에서

    • RazorPagesPizzaAuthConnection 연결 문자열은 appsettings.json에서 읽습니다.
    • RazorPagesPizzaAuth라는 EF Core 데이터베이스 컨텍스트 클래스가 연결 문자열을 사용하여 구성됩니다.
    • 기본 UI, 토큰 공급자 및 쿠키 기반 인증을 포함하는 ID 서비스가 등록됩니다.
      • .AddDefaultIdentity<IdentityUser>는 ID 서비스에 기본 사용자 모델을 사용하도록 지시합니다.
      • options => options.SignIn.RequireConfirmedAccount = true 람다 식은 사용자가 자신의 메일 계정을 확인해야 한다고 지정합니다.
      • .AddEntityFrameworkStores<RazorPagesPizzaAuth>()는 ID가 해당 데이터베이스에 대해 기본 Entity Framework Core 저장소를 사용한다고 지정합니다. RazorPagesPizzaAuthDbContext 클래스가 사용됩니다.

데이터베이스 연결 구성

appsettings.jsonConnectionStrings 섹션은 다음 JSON과 유사해야 합니다.

"ConnectionStrings": {
    "RazorPagesPizzaAuthConnection": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesPizza;Trusted_Connection=True;MultipleActiveResultSets=true"
}

이 연결 문자열은 기본적으로 SQL Server Express LocalDB 인스턴스를 가리킵니다. 로컬로 개발하는 경우 아무것도 하지 마세요. 이는 올바른 연결 문자열입니다.

Codespaces 또는 Dev Container에서 연결 문자열이 잘못되었습니다. Codespace 또는 Dev Container를 사용하는 경우 다음과 같이 연결 문자열을 변경해야 합니다. 변경 내용을 저장해야 합니다.

"ConnectionStrings": {
    "RazorPagesPizzaAuthConnection": "Data Source=localhost;Initial Catalog=RazorPagesPizza;Integrated Security=False;User Id=sa;Password=P@ssw0rd;MultipleActiveResultSets=True;Encrypt=False"
}

그러면 컨테이너 내의 SQL Server 인스턴스에 연결하도록 연결 문자열이 업데이트됩니다.

데이터베이스 업데이트

이제 연결 문자열 확인했으므로 마이그레이션을 생성하고 실행하여 데이터베이스를 빌드할 수 있습니다.

  1. 다음 명령을 실행하여 앱을 빌드합니다.

    dotnet build
    

    빌드는 경고 없이 성공합니다. 빌드가 실패하면 출력에서 문제 해결 정보를 확인하세요.

  2. Entity Framework Core 마이그레이션 도구를 설치합니다.

    dotnet tool install dotnet-ef --version 8.0.* --global
    

    마이그레이션 도구는 다음을 수행하는 .NET 도구입니다.

    • 마이그레이션이라는 코드를 생성하여 ID 엔터티 모델을 지원하는 데이터베이스를 만들고 업데이트합니다.
    • 기존 데이터베이스에 대해 마이그레이션을 실행합니다.
    • 이 모듈에서 dotnet ef를 통해 호출됩니다.
  3. 데이터베이스를 업데이트하려면 EF Core 마이그레이션을 만들고 실행합니다.

    dotnet ef migrations add CreateIdentitySchema
    dotnet ef database update
    

    CreateIdentitySchema EF Core 마이그레이션은 DDL(데이터 정의 언어) 변경 스크립트를 적용하여 ID를 지원하는 테이블을 만들었습니다. 예를 들어 다음 출력 내용은 마이그레이션에서 생성된 CREATE TABLE 문을 보여 줍니다.

    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (98ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
          CREATE TABLE [AspNetUsers] (
              [Id] nvarchar(450) NOT NULL,
              [UserName] nvarchar(256) NULL,
              [NormalizedUserName] nvarchar(256) NULL,
              [Email] nvarchar(256) NULL,
              [NormalizedEmail] nvarchar(256) NULL,
              [EmailConfirmed] bit NOT NULL,
              [PasswordHash] nvarchar(max) NULL,
              [SecurityStamp] nvarchar(max) NULL,
              [ConcurrencyStamp] nvarchar(max) NULL,
              [PhoneNumber] nvarchar(max) NULL,
              [PhoneNumberConfirmed] bit NOT NULL,
              [TwoFactorEnabled] bit NOT NULL,
              [LockoutEnd] datetimeoffset NULL,
              [LockoutEnabled] bit NOT NULL,
              [AccessFailedCount] int NOT NULL,
              CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id])
          );
    

    ef 명령이 지원되지 않는 LocalDb에 대한 오류를 throw했나요? "데이터베이스 연결 구성" 섹션에 설명된 대로 연결 문자열을 설정했는지 확인합니다.

  4. 권장 확장을 수락하면 SQL Server 확장이 Visual Studio Code에 추가되었습니다(필요한 경우). Ctrl+Alt+D를 눌러 SQL Server 창으로 전환합니다.

  5. 기존 데이터베이스 연결 아래의 노드를 확장합니다. 데이터베이스 노드, RazorPagesPizza 노드 및 마지막으로 테이블 노드를 확장합니다. 테이블 목록을 확인합니다. 이렇게 하면 마이그레이션이 성공했는지 확인합니다.

    새로 만든 테이블이 있는 RazorPagesPizza 데이터베이스.

    참고

    위의 이미지는 SQL Server Express LocalDB 사용하는 예제를 보여 줍니다. .devcontainer를 사용하는 경우 연결 이름은 mssql-container입니다.

탐색기 창으로 돌아갑니다. Pages/Shared/_Layout.cshtml, 에서 @* Add the _LoginPartial partial view *@ 주석을 다음 코드로 바꿉니다.

<partial name="_LoginPartial" />

위의 태그는 기본 레이아웃을 사용하는 페이지의 머리글 내에서 _LoginPartial 부분 뷰를 렌더링합니다. ID 스캐폴드가 추가 _LoginPartial되었습니다. 이 부분 뷰는 사용자가 로그인하지 않은 경우 로그인등록 링크를 제공합니다.

ID 기능 테스트

이것이 기본 ID 구현을 추가하는 데 필요한 모든 것입니다. 이제 테스트할 시간입니다!

  1. 모든 변경 내용을 저장해야 합니다.

  2. 터미널 창에서 프로젝트를 빌드하고 앱을 실행합니다.

    dotnet run
    
  3. 이전과 같이 브라우저에서 앱으로 이동합니다.

  4. 앱의 헤더에서 등록 링크를 선택합니다. 양식을 완료하여 새 계정을 만듭니다.

    확인 등록 페이지가 표시됩니다. 앱이 확인 전자 메일을 보내도록 구성되지 않았으므로 이 페이지에 확인 링크가 제공됩니다.

  5. 확인 링크를 선택합니다. 확인 메시지가 표시됩니다.

  6. 앱의 헤더에서 로그인 링크를 선택하고 로그인합니다.

    로그인 성공 후:

    • 홈페이지로 리디렉션됩니다.
    • 앱의 헤더에 Hello [이메일 주소]!로그아웃 링크가 표시됩니다.
    • .AspNetCore.Identity.Application이라는 쿠키가 생성됩니다. ID는 쿠키 기반 인증을 사용하여 사용자 세션을 유지합니다.
  7. 앱의 헤더에서 로그아웃 링크를 선택합니다.

    성공적으로 로그아웃되면 .AspNetCore.Identity.Application 쿠키가 삭제되어 사용자 세션이 종료됩니다.

  8. 앱을 중지하려면 터미널 창에서 Ctrl+C를 누릅니다.

요약

이 단원에서는 기존 웹앱에 기본 ID 구현을 추가했습니다. 다음 단원에서는 ID 확장 및 사용자 지정에 대해 알아봅니다.