ASP.NET Core 프로젝트의 스캐폴드 Identity

작성자: Rick Anderson

ASP.NET Core에서는 ASP.NET Core Identity를 Razor 클래스 라이브러리로 제공합니다. Identity가 포함되는 애플리케이션은 스캐폴더를 적용하여 IdentityRazor RCL(클래스 라이브러리)에 포함된 소스 코드를 선택적으로 추가할 수 있습니다. 코드를 수정하고 동작을 변경할 수 있도록 소스 코드를 생성할 수 있습니다. 예를 들어 등록에 사용된 코드를 생성하도록 스캐폴더를 지정할 수 있습니다. 생성된 코드는 Identity RCL의 동일한 코드보다 우선합니다. 기본 RCL을 사용하지 않고 UI의 모든 권한을 얻으려면 전체 Identity UI 원본 만들기 섹션을 참조하세요.

인증을 포함하지 않는 애플리케이션은 RCL Identity 패키지를 추가하기 위해 스캐폴더를 적용할 수 있습니다. 선택한 Identity 코드의 옵션이 생성되어야 합니다.

스캐폴더는 필요한 코드를 대부분 생성하지만 프로젝트를 업데이트하여 프로세스를 완료해야 합니다. 이 문서에서는 Identity 스캐폴딩 업데이트를 완료하는 데 필요한 단계를 설명합니다.

파일 차이를 표시하고 변경 내용을 취소할 수 있는 소스 제어 시스템을 사용하는 것이 좋습니다. Identity 스캐폴더를 실행한 후 변경 내용을 검사합니다.

Identity와 함께 2단계 인증, 계정 확인 및 암호 복구, 기타 보안 기능을 사용하는 경우 서비스가 필요합니다. 서비스 또는 서비스 스텁은 Identity를 스캐폴딩할 때 생성되지 않습니다. 이러한 기능을 사용하도록 설정하는 서비스는 수동으로 추가해야 합니다. 예를 들어 이메일 확인 필요를 참조하세요.

일반적으로 개별 계정으로 만든 앱은 새 데이터 컨텍스트를 만들지 않아야 합니다.

기존 권한 없이 Razor 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

마이그레이션, UseAuthentication 및 레이아웃

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

레이아웃 변경

선택 사항: 레이아웃 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

권한 있는 Razor 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

기존 권한 없이 MVC 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

선택 사항: Views/Shared/_Layout.cshtml 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

다음 강조 표시된 코드에 표시된 대로 Program.csMapRazorPages를 추가합니다.

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

권한 있는 MVC 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

클라이언트 쪽 Blazor 앱

클라이언트 쪽 Blazor 앱은 자체 Identity UI 접근 방식을 사용하며 ASP.NET Core Identity 스캐폴딩을 사용할 수 없습니다.

서버 쪽 ASP.NET Core 앱은 이 문서의 Pages/MVC 지침을 따를 Razor 수 있으며 지원하는 다른 유형의 ASP.NET Core 앱과 마찬가지로 구성됩니다 Identity. 프레임워크는 Blazor 웹앱으로 스캐폴딩할 때 UI 페이지()의 Identity 구성 요소 버전(.cshtml.razor)을 IdentityBlazor 사용합니다Razor.

자세한 내용은 Blazor 보안 및 Identity 문서를 참조하세요.

전체 Identity UI 원본 만들기

Identity UI에 대한 모든 권한을 유지하려면 Identity 스캐폴더를 실행하고 모든 파일 재정의를 선택합니다.

암호 구성

PasswordOptionsStartup.ConfigureServices에 구성된 경우 스캐폴드된 Identity 페이지의 Password 속성에 대해 [StringLength] 특성 구성이 필요할 수 있습니다. InputModelPassword 속성은 다음 파일에 있습니다.

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

페이지 사용 안 함

이 섹션에서는 등록 페이지를 비활성화하는 방법을 보여주지만, 이 방식을 사용하여 모든 페이지를 비활성화할 수 있습니다.

사용자 등록을 사용하지 않도록 설정하려면 다음을 수행합니다.

  • 스캐폴드 Identity. Account.Register, Account.Login 및 Account.RegisterConfirmation을 포함합니다. 예시:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • 사용자가 이 엔드포인트에서 등록할 수 없도록 Areas/Identity/Pages/Account/Register.cshtml.cs를 업데이트합니다.

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • 앞의 변경 내용과 일치하도록 Areas/Identity/Pages/Account/Register.cshtml를 업데이트합니다.

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Areas/Identity/Pages/Account/Login.cshtml에서 등록 링크를 주석으로 처리하거나 제거합니다.

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Areas/Identity/Pages/Account/RegisterConfirmation 페이지를 업데이트합니다.

    • cshtml 파일에서 코드 및 링크를 제거합니다.
    • PageModel에서 확인 코드를 제거합니다.
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

다른 앱을 사용하여 사용자 추가

웹앱 외부에 사용자를 추가하는 메커니즘을 제공합니다. 사용자를 추가하는 옵션은 다음과 같습니다.

  • 전용 관리 웹앱입니다.
  • 콘솔 앱.

다음 코드에서는 사용자를 추가하는 한 가지 방법을 간략하게 설명합니다.

  • 사용자 목록을 메모리로 읽습니다.
  • 각 사용자에 대해 강력한 고유 암호가 생성됩니다.
  • 사용자가 Identity 데이터베이스에 추가됩니다.
  • 사용자에게 알림이 표시되고 암호를 변경하라는 메시지가 표시됩니다.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

다음 코드에서는 사용자를 추가하는 방법을 간략하게 설명합니다.


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

프로덕션 시나리오에 대해서도 유사한 접근 방식을 따를 수 있습니다.

정적 Identity 자산 게시 방지

정적 Identity 자산을 웹 루트에 게시하지 않도록 하려면 ASP.NET Core에 Identity 도입을 참조하세요.

ASP.NET Core에서는 ASP.NET Core Identity를 Razor 클래스 라이브러리로 제공합니다. Identity가 포함되는 애플리케이션은 스캐폴더를 적용하여 IdentityRazor RCL(클래스 라이브러리)에 포함된 소스 코드를 선택적으로 추가할 수 있습니다. 코드를 수정하고 동작을 변경할 수 있도록 소스 코드를 생성할 수 있습니다. 예를 들어 등록에 사용된 코드를 생성하도록 스캐폴더를 지정할 수 있습니다. 생성된 코드는 Identity RCL의 동일한 코드보다 우선합니다. 기본 RCL을 사용하지 않고 UI의 모든 권한을 얻으려면 전체 Identity UI 원본 만들기 섹션을 참조하세요.

인증을 포함하지 않는 애플리케이션은 RCL Identity 패키지를 추가하기 위해 스캐폴더를 적용할 수 있습니다. 선택한 Identity 코드의 옵션이 생성되어야 합니다.

스캐폴더는 필요한 코드를 대부분 생성하지만 프로젝트를 업데이트하여 프로세스를 완료해야 합니다. 이 문서에서는 Identity 스캐폴딩 업데이트를 완료하는 데 필요한 단계를 설명합니다.

파일 차이를 표시하고 변경 내용을 취소할 수 있는 소스 제어 시스템을 사용하는 것이 좋습니다. Identity 스캐폴더를 실행한 후 변경 내용을 검사합니다.

Identity와 함께 2단계 인증, 계정 확인 및 암호 복구, 기타 보안 기능을 사용하는 경우 서비스가 필요합니다. 서비스 또는 서비스 스텁은 Identity를 스캐폴딩할 때 생성되지 않습니다. 이러한 기능을 사용하도록 설정하는 서비스는 수동으로 추가해야 합니다. 예를 들어 이메일 확인 필요를 참조하세요.

일반적으로 개별 계정으로 만든 앱은 새 데이터 컨텍스트를 만들지 않아야 합니다.

기존 권한 없이 Razor 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

마이그레이션, UseAuthentication 및 레이아웃

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

레이아웃 변경

선택 사항: 레이아웃 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

권한 있는 Razor 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

기존 권한 없이 MVC 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

선택 사항: Views/Shared/_Layout.cshtml 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

다음 강조 표시된 코드에 표시된 대로 Program.csMapRazorPages를 추가합니다.

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

권한 있는 MVC 프로젝트로 Identity를 스캐폴드합니다.

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

권한 부여를 사용하여 서버 쪽 Blazor 앱으로 스캐폴드 Identity

Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 패키지를 설치합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.


Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

마이그레이션

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

스타일 인증 엔드포인트

서버 쪽 Blazor 앱은 페이지 Identity 페이지를 사용 Razor 하므로 방문자가 페이지와 구성 요소 사이 Identity 를 탐색할 때 UI의 스타일이 변경됩니다. 부적합한 스타일을 처리하는 두 가지 옵션이 있습니다.

사용자 지정 Identity 구성 요소

ASP.NET Core Identity는 Blazor 앱에서 기본 클라이언트-서버 커뮤니케이션 모델이 아닌 HTTP 요청 및 응답 커뮤니케이션의 컨텍스트에서 작동하도록 설계되었습니다. 사용자 관리에 ASP.NET Core Identity를 사용하는 ASP.NET Core 앱은 사용자 등록, 로그인, 로그아웃 및 기타 사용자 관리 작업과 같은 Identity 관련 UI에 Razor 구성 요소 대신 Razor Pages를 사용해야 합니다.

SignInManager<TUser>UserManager<TUser>는 Razor 구성 요소에서 지원되지 않으므로 웹 API를 사용하여 서버 쪽 Identity지원 ASP.NET Core 앱을 통해 Razor 구성 요소의 Identity 작업을 관리하는 것이 좋습니다. Blazor 앱용 웹 API를 만드는 방법에 대한 지침은 ASP.NET Core Blazor 앱에서 웹 API 호출을 참조하세요.

Razor 페이지 대신 Identity에 대해 Razor 구성 요소를 사용하는 방법은 고유한 사용자 지정 IdentityRazor 구성 요소를 빌드하는 것이지만 Microsoft는 이 방법을 권장하거나 지원하지 않습니다. 추가 컨텍스트를 보려면 다음 토론을 살펴보세요. 다음 토론에서는 Microsoft가 아닌 GitHub 리포지토리에서 교차 연결된 문제 주석 및 코드 예제의 코드 예제가 Microsoft에서 지원되지 않지만 일부 개발자에게 도움이 될 수 있습니다.

사용자 지정 IdentityRazor 구성 요소를 빌드하거나 타사 Razor 구성 요소를 검색할 때 추가 지원을 받으려면 다음 리소스를 사용하는 것이 좋습니다.

Blazor 앱 스타일과 함께 사용자 지정 레이아웃 사용

Identity 페이지 레이아웃 및 스타일을 수정하여 기본 Blazor 테마와 유사한 스타일을 사용하는 페이지를 생성할 수 있습니다. 이 방법은 설명서에서 다루지 않습니다.

클라이언트 쪽 Blazor 앱

클라이언트 쪽 Blazor 앱은 자체 Identity UI 접근 방식을 사용하며 ASP.NET Core Identity 스캐폴딩을 사용할 수 없습니다. 호스트된 Blazor 솔루션의 서버 쪽 ASP.NET Core 앱은 이 문서의 Razor Pages/MVC 지침을 따를 수 있으며 Identity를 지원하는 다른 유형의 ASP.NET Core 앱과 마찬가지로 구성됩니다.

Blazor 프레임워크에는 Identity UI 페이지의 Razor 구성 요소 버전이 포함되어 있지 않습니다. Identity UI Razor 구성 요소는 사용자 지정 빌드되거나 지원되지 않는 타사 원본에서 가져올 수 있습니다.

자세한 내용은 Blazor 보안 및 Identity 문서를 참조하세요.

전체 Identity UI 원본 만들기

Identity UI에 대한 모든 권한을 유지하려면 Identity 스캐폴더를 실행하고 모든 파일 재정의를 선택합니다.

암호 구성

PasswordOptionsStartup.ConfigureServices에 구성된 경우 스캐폴드된 Identity 페이지의 Password 속성에 대해 [StringLength] 특성 구성이 필요할 수 있습니다. InputModelPassword 속성은 다음 파일에 있습니다.

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

페이지 사용 안 함

이 섹션에서는 등록 페이지를 비활성화하는 방법을 보여주지만, 이 방식을 사용하여 모든 페이지를 비활성화할 수 있습니다.

사용자 등록을 사용하지 않도록 설정하려면 다음을 수행합니다.

  • 스캐폴드 Identity. Account.Register, Account.Login 및 Account.RegisterConfirmation을 포함합니다. 예시:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • 사용자가 이 엔드포인트에서 등록할 수 없도록 Areas/Identity/Pages/Account/Register.cshtml.cs를 업데이트합니다.

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • 앞의 변경 내용과 일치하도록 Areas/Identity/Pages/Account/Register.cshtml를 업데이트합니다.

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Areas/Identity/Pages/Account/Login.cshtml에서 등록 링크를 주석으로 처리하거나 제거합니다.

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Areas/Identity/Pages/Account/RegisterConfirmation 페이지를 업데이트합니다.

    • cshtml 파일에서 코드 및 링크를 제거합니다.
    • PageModel에서 확인 코드를 제거합니다.
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

다른 앱을 사용하여 사용자 추가

웹앱 외부에 사용자를 추가하는 메커니즘을 제공합니다. 사용자를 추가하는 옵션은 다음과 같습니다.

  • 전용 관리 웹앱입니다.
  • 콘솔 앱.

다음 코드에서는 사용자를 추가하는 한 가지 방법을 간략하게 설명합니다.

  • 사용자 목록을 메모리로 읽습니다.
  • 각 사용자에 대해 강력한 고유 암호가 생성됩니다.
  • 사용자가 Identity 데이터베이스에 추가됩니다.
  • 사용자에게 알림이 표시되고 암호를 변경하라는 메시지가 표시됩니다.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

다음 코드에서는 사용자를 추가하는 방법을 간략하게 설명합니다.


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

프로덕션 시나리오에 대해서도 유사한 접근 방식을 따를 수 있습니다.

정적 Identity 자산 게시 방지

정적 Identity 자산을 웹 루트에 게시하지 않도록 하려면 ASP.NET Core에 Identity 도입을 참조하세요.

ASP.NET Core에서는 ASP.NET Core Identity를 Razor 클래스 라이브러리로 제공합니다. Identity가 포함되는 애플리케이션은 스캐폴더를 적용하여 IdentityRazor RCL(클래스 라이브러리)에 포함된 소스 코드를 선택적으로 추가할 수 있습니다. 코드를 수정하고 동작을 변경할 수 있도록 소스 코드를 생성할 수 있습니다. 예를 들어 등록에 사용된 코드를 생성하도록 스캐폴더를 지정할 수 있습니다. 생성된 코드는 Identity RCL의 동일한 코드보다 우선합니다. 기본 RCL을 사용하지 않고 UI의 모든 권한을 얻으려면 전체 Identity UI 원본 만들기 섹션을 참조하세요.

인증을 포함하지 않는 애플리케이션은 RCL Identity 패키지를 추가하기 위해 스캐폴더를 적용할 수 있습니다. 선택한 Identity 코드의 옵션이 생성되어야 합니다.

스캐폴더는 필요한 코드를 대부분 생성하지만 프로젝트를 업데이트하여 프로세스를 완료해야 합니다. 이 문서에서는 Identity 스캐폴딩 업데이트를 완료하는 데 필요한 단계를 설명합니다.

파일 차이를 표시하고 변경 내용을 취소할 수 있는 소스 제어 시스템을 사용하는 것이 좋습니다. Identity 스캐폴더를 실행한 후 변경 내용을 검사합니다.

Identity와 함께 2단계 인증, 계정 확인 및 암호 복구, 기타 보안 기능을 사용하는 경우 서비스가 필요합니다. 서비스 또는 서비스 스텁은 Identity를 스캐폴딩할 때 생성되지 않습니다. 이러한 기능을 사용하도록 설정하는 서비스는 수동으로 추가해야 합니다. 예를 들어 이메일 확인 필요를 참조하세요.

새 데이터 컨텍스트가 있는 Identity를 기존 개별 계정이 있는 프로젝트로 스캐폴딩하는 경우:

  • 에서 Startup.ConfigureServices다음 호출을 제거합니다.
    • AddDbContext
    • AddDefaultIdentity

예를 들어 AddDbContextAddDefaultIdentity는 다음 코드에서 주석으로 처리됩니다.

public void ConfigureServices(IServiceCollection services)
{
    //services.AddDbContext<ApplicationDbContext>(options =>
    //    options.UseSqlServer(
    //        Configuration.GetConnectionString("DefaultConnection")));
    //services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    //    .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddControllersWithViews();
    services.AddRazorPages();
}

위의 코드는 Areas/Identity/IdentityHostingStartup.cs에서 중복된 코드를 주석 처리합니다.

일반적으로 개별 계정으로 만든 앱은 새 데이터 컨텍스트를 만들지 않아야 합니다.

빈 프로젝트로 Identity를 스캐폴드합니다.

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

Startup 클래스를 다음과 유사한 코드로 업데이트합니다.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

UseHsts는 권장되지만 필수는 아닙니다. 자세한 내용은 HTTP 엄격한 전송 보안 프로토콜을 참조하세요.

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

기존 권한 없이 Razor 프로젝트로 Identity를 스캐폴드합니다.

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

Identity는 Areas/Identity/IdentityHostingStartup.cs에서 구성됩니다. 자세한 내용은 IHostingStartup을 참조하세요.

마이그레이션, UseAuthentication 및 레이아웃

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

인증 사용

Startup 클래스를 다음과 유사한 코드로 업데이트합니다.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

UseHsts는 권장되지만 필수는 아닙니다. 자세한 내용은 HTTP 엄격한 전송 보안 프로토콜을 참조하세요.

레이아웃 변경

선택 사항: 레이아웃 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

권한 있는 Razor 프로젝트로 Identity를 스캐폴드합니다.

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

일부 Identity 옵션은 Areas/Identity/IdentityHostingStartup.cs에서 구성됩니다. 자세한 내용은 IHostingStartup을 참조하세요.

기존 권한 없이 MVC 프로젝트로 Identity를 스캐폴드합니다.

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

선택 사항: Views/Shared/_Layout.cshtml 파일에 로그인 부분(_LoginPartial)을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>
  • Pages/Shared/_LoginPartial.cshtml 파일을 Views/Shared/_LoginPartial.cshtml로 이동

Identity는 Areas/Identity/IdentityHostingStartup.cs에서 구성됩니다. 자세한 내용은 IHostingStartup을 참조하세요.

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

Startup 클래스를 다음과 유사한 코드로 업데이트합니다.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

UseHsts는 권장되지만 필수는 아닙니다. 자세한 내용은 HTTP 엄격한 전송 보안 프로토콜을 참조하세요.

권한 있는 MVC 프로젝트로 Identity를 스캐폴드합니다.

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

기존 권한 부여 없이 서버 쪽 Blazor 앱으로 스캐폴드 Identity

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

Identity는 Areas/Identity/IdentityHostingStartup.cs에서 구성됩니다. 자세한 내용은 IHostingStartup를 참조하세요.

마이그레이션

생성된 Identity 데이터베이스 코드에는 Entity Framework Core 마이그레이션이 필요합니다. 스키마를 만들기 위한 마이그레이션이 Identity 만들어지고 데이터베이스에 적용되지 않은 경우 마이그레이션을 만들고 데이터베이스를 업데이트합니다. 예를 들어 다음 명령을 실행합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행합니다.

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration 명령에 대한 "CreateIdentitySchema" 이름 매개 변수는 임의적입니다. "CreateIdentitySchema"는 마이그레이션을 설명합니다.

스키마가 Identity 이미 만들어졌지만 데이터베이스에 적용되지 않은 경우 데이터베이스를 업데이트하는 명령만 실행해야 합니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Update-Database합니다.

Update-Database

다음 명령을 사용하여 스키마의 Identity 애플리케이션을 확인할 수 있습니다. 명령의 출력에는 데이터베이스에 적용되는 마이그레이션을 표시하는 "applied" 열이 포함됩니다.

Visual Studio 패키지 관리자 콘솔에서 다음을 실행Get-Migration합니다.

Get-Migration

둘 이상의 데이터베이스 컨텍스트가 있는 경우 매개 변수를 사용하여 컨텍스트를 -Context 지정합니다.

스타일 인증 엔드포인트

서버 쪽 Blazor 앱은 페이지 Identity 페이지를 사용 Razor 하므로 방문자가 페이지와 구성 요소 사이 Identity 를 탐색할 때 UI의 스타일이 변경됩니다. 부적합한 스타일을 처리하는 두 가지 옵션이 있습니다.

사용자 지정 Identity 구성 요소

페이지 대신 Identity에 대한 구성 요소를 사용하는 방식은 Identity 구성 요소를 빌드하는 것입니다. SignInManagerUserManager 구성 요소에서 Razor 지원되지 않으므로 앱의 웹 API 엔드포인트를 Blazor 사용하여 사용자 계정 작업을 처리합니다.

Blazor 앱 스타일과 함께 사용자 지정 레이아웃 사용

Identity 페이지 레이아웃 및 스타일을 수정하여 기본 Blazor 테마와 유사한 스타일을 사용하는 페이지를 생성할 수 있습니다. 이 방법은 설명서에서 다루지 않습니다.

권한 부여를 사용하여 서버 쪽 Blazor 앱으로 스캐폴드 Identity

Identity 스캐폴더를 실행합니다.

  • 솔루션 탐색기에서 프로젝트 > >추가>새 스캐폴드 항목을 마우스 오른쪽 단추로 클릭합니다.
  • 새 스캐폴드 항목 추가 대화 상자의 왼쪽 창에서 Identity를 선택합니다. 가운데 창에서 Identity를 선택합니다. 추가 단추를 선택합니다.
  • 추가 Identity 대화 상자에서 원하는 옵션을 선택합니다.
    • ()에 대해 Identity_Layout.cshtml사용자 지정된 기존 레이아웃 페이지가 있는 경우 기존 레이아웃 페이지를 선택하여 스캐폴더에서 잘못된 태그로 레이아웃을 덮어쓰지 않도록 합니다. 예를 들어 다음 중 하나를 선택합니다.
      • 기존 Razor Pages 인프라가 있는 Razor Pages 또는 Blazor Server 프로젝트의 경우 Pages/Shared/_Layout.cshtml.
      • 기존 MVC 인프라가 있는 MVC 프로젝트 또는 Blazor Server 프로젝트의 경우 Views/Shared/_Layout.cshtml.
    • 데이터 컨텍스트의 경우(DbContext 클래스):
      • 데이터 컨텍스트 클래스를 선택합니다. 데이터 컨텍스트를 추가하려면 파일을 하나 이상 선택해야 합니다.
      • 데이터 컨텍스트를 만들고 새 사용자 클래스를 Identity만들려면 단추를 선택합니다 + . 기본값을 적용하거나 클래스를 지정합니다(예 Contoso.Data.ApplicationDbContext : "Contoso"라는 회사의 경우). 새 사용자 클래스를 만들려면 사용자 클래스에 + 대한 단추를 선택하고 클래스를 지정합니다(예: ContosoUser "Contoso"라는 회사의 경우).
    • 추가 단추를 선택하여 스캐폴더를 실행합니다.

일부 Identity 옵션은 Areas/Identity/IdentityHostingStartup.cs에서 구성됩니다. 자세한 내용은 IHostingStartup을 참조하세요.

클라이언트 쪽 Blazor 앱

클라이언트 쪽 Blazor 앱은 자체 Identity UI 접근 방식을 사용하며 ASP.NET Core Identity 스캐폴딩을 사용할 수 없습니다. 호스트된 Blazor 솔루션의 서버 쪽 ASP.NET Core 앱은 이 문서의 Razor Pages/MVC 지침을 따를 수 있으며 Identity를 지원하는 다른 유형의 ASP.NET Core 앱과 마찬가지로 구성됩니다.

Blazor 프레임워크에는 Identity UI 페이지의 Razor 구성 요소 버전이 포함되어 있지 않습니다. Identity UI Razor 구성 요소는 사용자 지정 빌드되거나 지원되지 않는 타사 원본에서 가져올 수 있습니다.

자세한 내용은 Blazor 보안 및 Identity 문서를 참조하세요.

전체 Identity UI 원본 만들기

Identity UI에 대한 모든 권한을 유지하려면 Identity 스캐폴더를 실행하고 모든 파일 재정의를 선택합니다.

다음 강조 표시된 코드는 ASP.NET Core 2.1 웹앱에서 기본 Identity UI를 Identity로 바꾸는 변경 내용을 보여줍니다. 이 작업을 수행하여 Identity UI에 대한 모든 권한을 부여할 수 있습니다.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<IdentityUser, IdentityRole>()
        // services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
    });

    // using Microsoft.AspNetCore.Identity.UI.Services;
    services.AddSingleton<IEmailSender, EmailSender>();
}

기본값 Identity는 다음 코드에서 대체됩니다.

services.AddIdentity<IdentityUser, IdentityRole>()
    // services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

다음 코드는 LoginPath, LogoutPathAccessDeniedPath을 설정합니다.

services.ConfigureApplicationCookie(options =>
{
    options.LoginPath = $"/Identity/Account/Login";
    options.LogoutPath = $"/Identity/Account/Logout";
    options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});

IEmailSender 구현을 등록합니다. 예를 들면 다음과 같습니다.

// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
public class EmailSender : IEmailSender
{
    public Task SendEmailAsync(string email, string subject, string message)
    {
        return Task.CompletedTask;
    }
}

암호 구성

PasswordOptionsStartup.ConfigureServices에 구성된 경우 스캐폴드된 Identity 페이지의 Password 속성에 대해 [StringLength] 특성 구성이 필요할 수 있습니다. InputModelPassword 속성은 다음 파일에 있습니다.

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

페이지 사용 안 함

이 섹션에서는 등록 페이지를 비활성화하는 방법을 보여주지만, 이 방식을 사용하여 모든 페이지를 비활성화할 수 있습니다.

사용자 등록을 사용하지 않도록 설정하려면 다음을 수행합니다.

  • 스캐폴드 Identity. Account.Register, Account.Login 및 Account.RegisterConfirmation을 포함합니다. 예시:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • 사용자가 이 엔드포인트에서 등록할 수 없도록 Areas/Identity/Pages/Account/Register.cshtml.cs를 업데이트합니다.

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • 앞의 변경 내용과 일치하도록 Areas/Identity/Pages/Account/Register.cshtml를 업데이트합니다.

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Areas/Identity/Pages/Account/Login.cshtml에서 등록 링크를 주석으로 처리하거나 제거합니다.

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Areas/Identity/Pages/Account/RegisterConfirmation 페이지를 업데이트합니다.

    • cshtml 파일에서 코드 및 링크를 제거합니다.
    • PageModel에서 확인 코드를 제거합니다.
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

다른 앱을 사용하여 사용자 추가

웹앱 외부에 사용자를 추가하는 메커니즘을 제공합니다. 사용자를 추가하는 옵션은 다음과 같습니다.

  • 전용 관리 웹앱입니다.
  • 콘솔 앱.

다음 코드에서는 사용자를 추가하는 한 가지 방법을 간략하게 설명합니다.

  • 사용자 목록을 메모리로 읽습니다.
  • 각 사용자에 대해 강력한 고유 암호가 생성됩니다.
  • 사용자가 Identity 데이터베이스에 추가됩니다.
  • 사용자에게 알림이 표시되고 암호를 변경하라는 메시지가 표시됩니다.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

다음 코드에서는 사용자를 추가하는 방법을 간략하게 설명합니다.


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

프로덕션 시나리오에 대해서도 유사한 접근 방식을 따를 수 있습니다.

정적 Identity 자산 게시 방지

정적 Identity 자산을 웹 루트에 게시하지 않도록 하려면 ASP.NET Core에 Identity 도입을 참조하세요.

추가 리소스