ASP.NET Core の Identity 概要

作成者: Rick Anderson

ASP.NET Core Identity:

  • ユーザー インターフェイス (UI) ログイン機能をサポートする API です。
  • ユーザー、パスワード、プロファイル データ、ロール、要求、トークン、電子メールの確認などについて管理します。

ユーザーは、 に格納されているログイン情報を持つアカウントを作成するか、 Identity 外部ログイン プロバイダーを使用できます。 サポートされている外部ログイン プロバイダーには 、Facebook、Google、Microsoft アカウント、Twitter があります

すべてのユーザーの認証をグローバルに要求する方法の詳細については、「認証されたユーザーを要求する」を参照してください。

ソース Identity コードは、次のGitHub。 ス Identity キャフォールディング生成されたファイルを表示して、 とのテンプレートの相互作用を確認します Identity 。

Identityは通常、ユーザー名、パスワードSQL Serverプロファイル データを格納するために、データベースを使用して構成されます。 または、別の永続ストア (Azure Table Storage など) を使用できます。

このトピックでは、 を使用して、ユーザー Identity の登録、ログイン、およびログアウトを行う方法について説明します。 注: テンプレートでは、ユーザー名と電子メールはユーザーと同じとして扱います。 を使用するアプリの作成に関する詳細な手順については、「次 Identity の手順」 を参照してください

Microsoft ID プラットフォームは次の場合です。

  • Azure Active Directory (Azure AD) 開発者プラットフォームの進化。
  • とは無関係 ASP.NET Core Identity です。

ASP.NET Core Identity では、ASP.NET Core Web アプリにユーザー インターフェイス (UI) ログイン機能が追加されます。 Web API と SPA をセキュリティで保護するには、次のいずれかを使用します。

IdentityServer4 は、ASP.NET Core 用の OpenID Connect および OAuth 2.0 フレームワークです。 IdentityServer4 により、次のセキュリティ機能が有効になります。

  • サービスとしての認証 (AaaS)
  • 複数のアプリケーションの種類でのシングル サインオン/オフ (SSO)
  • API のアクセス制御
  • Federation Gateway

詳細については、「ようこそ! IdentityServer4」を参照してください。

サンプル コード (ダウンロード方法 )を表示またはダウンロードします

認証を使用して Web アプリを作成する

個々のユーザー アカウント ASP.NET Core Web アプリケーション プロジェクトを作成します。

  • [Web アプリ ASP.NET Coreテンプレートを選択 します。 プロジェクトに WebApp1 という名前を 付け、プロジェクトのダウンロードと同じ名前空間を使用します。 [OK] をクリックします。
  • [認証の 種類] 入力で 、[個々のユーザー アカウント ] を選択します

生成されたプロジェクトは、 ASP.NET Core Identity クラス ライブラリ として Razor 提供されます。 クラス Identity Razor ライブラリは、 領域を持つエンドポイントを公開 Identity します。 例:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Account/Manage

移行を適用する

移行を適用してデータベースを初期化します。

パッケージ マネージャー コンソール (PMC) で次のコマンドを実行します。

Update-Database

登録とログインのテスト

アプリを実行し、ユーザーを登録します。 画面のサイズによっては、ナビゲーショントグル ボタンを選択して [登録] リンクと [ログイン] リンクを表示 する 必要がある場合 があります。

データベースを表示 Identity する

  • [表示] メニュー[SQL Server オブジェクト エクスプローラー (SSOX) を選択します。
  • (localdb)MSSQLLocalDB(SQL Server 13) に移動します。 dbo を右 クリックします。AspNetUsers > View Data:

AspNetUsers テーブルのコンテキスト メニュー (SQL Server オブジェクト エクスプローラー

サービスを Identity 構成する

サービスは Program.cs に追加されます。 一般的なパターンは、次の順序でメソッドを呼び出すパターンです。

  1. Add{Service}
  2. Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.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.AddRazorPages();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
});

var app = builder.Build();

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

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

app.UseRouting();

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

app.MapRazorPages();

app.Run();

前のコードは、既定の Identity オプション値を使用して を構成します。 サービスは、依存関係の挿入 によってアプリ で使用できます

Identity は 、UseAuthentication を呼び出すことによって有効になりますUseAuthentication は、要求 パイプライン に認証ミドルウェアを追加します。

テンプレートで生成されたアプリでは、承認 は使用 されませんapp.UseAuthorization は、アプリが承認を追加した場合に正しい順序で追加されていることを確認するために含まれています。 UseRouting``UseAuthentication UseAuthorization 、、、および は UseEndpoints 、前のコードに示されている順序で呼び出す必要があります。

の詳細については、「」および「 IdentityOptions IdentityOptions アプリケーションの起動」 を参照してください

スキャフォールディング レジスタ、ログイン、ログアウト、RegisterConfirmation

Register、、、 Login および LogOut ファイルを追加 RegisterConfirmation します。 承認手順 を使用してプロジェクトに ID Razor を スキャフォールディングし、このセクションに示すコードを生成します。

レジスタの確認

ユーザーがページの [ 登録] ボタン をクリックすると Register 、アクション RegisterModel.OnPostAsync が呼び出されます。 ユーザーは、 オブジェクトの CreateAsync によって作成 _userManager されます。

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

既定のアカウント検証を無効にする

既定のテンプレートでは、ユーザーは にリダイレクトされ、アカウントを確認するリンク Account.RegisterConfirmation を選択できます。 既定値は Account.RegisterConfirmation テスト にのみ 使用されます。実稼働アプリではアカウントの自動検証を無効にする必要があります。

確認済みアカウントを要求し、登録時に即時ログインを防ぐには DisplayConfirmAccountLink = false 、/Areas/ Identity /Pages/Account/RegisterConfirmation.cshtml.cs で を設定します。

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

ログイン

ログイン フォームは、次の場合に表示されます。

  • [ ログイン] リンクが選択されています。
  • ユーザーは、アクセスが承認されていない、またはシステムによって認証されていない制限付きページへのアクセスを試みる。

[ログイン] ページのフォームが送信されると、アクション OnPostAsync が呼び出されます。 PasswordSignInAsync が オブジェクトで呼び出 _signInManager されます。

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

承認の決定を行う方法については、「」を参照してください ASP.NET Core での承認の概要

ログアウト

[ ログアウト] リンク によってアクションが呼び出 LogoutModel.OnPost されます。

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

前のコードでは、ブラウザーが新しい要求を実行し、ユーザーの ID を更新するために、コードをリダイレクト return RedirectToPage(); する必要があります。

SignOutAsync は 、 に格納されているユーザーの要求をクリアします cookie 。

Post は Pages/Shared/_LoginPartial.cshtml で指定されます

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

テスト Identity

既定の Web プロジェクト テンプレートでは、ホーム ページへの匿名アクセスが許可されます。 をテストするには Identity 、 を追加します [Authorize]

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

サインインしている場合は、サインアウトします。アプリを実行し、リンクを Privacy 選択します。 ログイン ページにリダイレクトされます。

探索 Identity

詳細については Identity 、次の手順を参照してください。

Identity コンポーネント

すべての Identity -dependent NuGetパッケージは、共有フレームワークの ASP.NET Coreに含まれています

のプライマリ パッケージ Identity はMicrosoft.AspNetCore Identity です。 このパッケージには、 のコア インターフェイス セットが含まれており ASP.NET Core Identity 、 によって含まれています Microsoft.AspNetCore.Identity.EntityFrameworkCore

への移行 ASP.NET Core Identity

既存のストアの移行に関する詳細とガイダンスについては、「Migrate Authentication and 」を Identity 参照 Identity してください

パスワードの強度の設定

パスワード の最小 要件を設定するサンプルについては、「構成」を参照してください。

AddDefault Identity と AddIdentity

AddDefaultIdentityは、ASP.NET Core 2.1 で導入されました。 の呼 AddDefaultIdentity び出しは、次の呼び出しに似ています。

詳細については 、AddDefault Identity ソースに関 するページを参照してください。

静的アセットの発行を防止 Identity する

静的アセット (UI 用のスタイルシートと JavaScript ファイル) が Web ルートに発行されるのを防ぐには、次のプロパティとターゲットをアプリのプロジェクト ファイル Identity Identity ResolveStaticWebAssetsInputsDependsOn RemoveIdentityAssets に追加します。

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

次の手順

作成者: Rick Anderson

ASP.NET Core Identity:

  • ユーザー インターフェイス (UI) ログイン機能をサポートする API です。
  • ユーザー、パスワード、プロファイル データ、ロール、要求、トークン、電子メールの確認などについて管理します。

ユーザーは、 に格納されているログイン情報を持つアカウントを作成するか、 Identity 外部ログイン プロバイダーを使用できます。 サポートされている外部ログイン プロバイダーには 、Facebook、Google、Microsoft アカウント、Twitter があります

すべてのユーザーの認証をグローバルに要求する方法の詳細については、「認証されたユーザーを要求する」を参照してください。

ソース Identity コードは、次のGitHub。 ス Identity キャフォールディング生成されたファイルを表示して、 とのテンプレートの相互作用を確認します Identity 。

Identityは通常、ユーザー名、パスワードSQL Serverプロファイル データを格納するデータベースを使用して構成されます。 または、別の永続ストア (Azure Table Storage など) を使用できます。

このトピックでは、 を使用して、ユーザー Identity の登録、ログイン、およびログアウトを行う方法について説明します。 注: テンプレートでは、ユーザー名と電子メールはユーザーと同じとして扱います。 を使用するアプリの作成に関する詳細な手順については、「次 Identity の手順」 を参照してください

Microsoft ID プラットフォームは次の場合です。

  • Azure Active Directory (Azure AD) 開発者プラットフォームの進化。
  • とは無関係 ASP.NET Core Identity です。

ASP.NET Core Identity では、ASP.NET Core Web アプリにユーザー インターフェイス (UI) ログイン機能が追加されます。 Web API と SPA をセキュリティで保護するには、次のいずれかを使用します。

IdentityServer4 は、ASP.NET Core 用の OpenID Connect および OAuth 2.0 フレームワークです。 IdentityServer4 により、次のセキュリティ機能が有効になります。

  • サービスとしての認証 (AaaS)
  • 複数のアプリケーションの種類でのシングル サインオン/オフ (SSO)
  • API のアクセス制御
  • Federation Gateway

詳細については、「ようこそ! IdentityServer4」を参照してください。

サンプル コード (ダウンロード方法 )を表示またはダウンロードします

認証を使用して Web アプリを作成する

個々のユーザー アカウント ASP.NET Core Web アプリケーション プロジェクトを作成します。

  • [ファイル ] > [新規] Project。 >
  • [ASP.NET Core Web アプリケーション] を選択します。 プロジェクトに WebApp1 という名前を 付け、プロジェクトのダウンロードと同じ名前空間を使用します。 [OK] をクリックします。
  • [Web アプリケーション] ASP.NET Core を選択し、[ 認証の変更]を選択します
  • [個々 のユーザー アカウント] を選択し**、[OK] をクリックします**。

生成されたプロジェクトは、 ASP.NET Core Identity クラス ライブラリ として Razor 提供されます。 クラス Identity Razor ライブラリは、 領域を持つエンドポイントを公開 Identity します。 例:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Account/Manage

移行を適用する

移行を適用してデータベースを初期化します。

次のコマンドを、パッケージ マネージャー コンソール (PMC) で実行します。

PM> Update-Database

登録とログインのテスト

アプリを実行し、ユーザーを登録します。 画面のサイズによっては、ナビゲーショントグル ボタンを選択して [登録] リンクと [ログイン] リンクを表示 する 必要がある場合 があります。

データベースを表示 Identity する

  • [表示] メニュー[SQL Server オブジェクト エクスプローラー (SSOX) を選択します。
  • (localdb)MSSQLLocalDB(SQL Server 13) に移動します。 dbo を右 クリックします。AspNetUsers > View Data:

AspNetUsers テーブルのコンテキスト メニュー (SQL Server オブジェクト エクスプローラー

サービスを Identity 構成する

サービスは に追加されます ConfigureServices 。 一般的なパターンは、すべての Add{Service} メソッドを呼び出した後、すべての services.Configure{Service} メソッドを呼び出すことです。

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

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

上の強調表示されているコードは、既定の Identity オプション値で構成されます。 サービスは、依存関係の挿入 によってアプリ で使用できます

Identity は、 を呼び出すことによって有効になります UseAuthenticationUseAuthentication は、要求 パイプライン に認証ミドルウェアを追加します。

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();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

前のコードは、既定の Identity オプション値を使用して を構成します。 サービスは、依存関係の挿入 によってアプリ で使用できます

Identity は 、UseAuthentication を呼び出すことによって有効になりますUseAuthentication は、要求 パイプライン に認証ミドルウェアを追加します。

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

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

    app.UseRouting();

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

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

テンプレートで生成されたアプリでは、承認 は使用 されませんapp.UseAuthorization は、アプリが承認を追加した場合に正しい順序で追加されていることを確認するために含まれています。 UseRouting``UseAuthentication UseAuthorization 、、、および は UseEndpoints 、前のコードに示されている順序で呼び出す必要があります。

と の詳細については IdentityOptions 、「 および アプリケーション Startup の起動 IdentityOptionsを参照してください

スキャフォールディング レジスタ、ログイン、ログアウト、RegisterConfirmation

Register、、、 Login および LogOut ファイルを追加 RegisterConfirmation します。 承認手順 を使用してプロジェクトに ID Razor を スキャフォールディングし、このセクションに示すコードを生成します。

レジスタの確認

ユーザーがページの [ 登録] ボタン をクリックすると Register 、アクション RegisterModel.OnPostAsync が呼び出されます。 ユーザーは、 オブジェクトの CreateAsync によって作成 _userManager されます。

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

既定のアカウント検証を無効にする

既定のテンプレートでは、ユーザーは にリダイレクトされ、アカウントを確認するリンク Account.RegisterConfirmation を選択できます。 既定値は Account.RegisterConfirmation テスト にのみ 使用されます。実稼働アプリではアカウントの自動検証を無効にする必要があります。

確認済みアカウントを要求し、登録時に即時ログインを防ぐには DisplayConfirmAccountLink = false 、/Areas/ Identity /Pages/Account/RegisterConfirmation.cshtml.cs で を設定します。

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

ログイン

ログイン フォームは、次の場合に表示されます。

  • [ ログイン] リンクが選択されています。
  • ユーザーは、アクセスが承認されていない、またはシステムによって認証されていない制限付きページへのアクセスを試みる。

[ログイン] ページのフォームが送信されると、アクション OnPostAsync が呼び出されます。 PasswordSignInAsync が オブジェクトで呼び出 _signInManager されます。

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

承認の決定を行う方法については、「」を参照してください ASP.NET Core での承認の概要

ログアウト

[ ログアウト] リンク によってアクションが呼び出 LogoutModel.OnPost されます。

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

前のコードでは、ブラウザーが新しい要求を実行し、ユーザーの ID を更新するために、コードをリダイレクト return RedirectToPage(); する必要があります。

SignOutAsync は 、 に格納されているユーザーの要求をクリアします cookie 。

Post は Pages/Shared/_LoginPartial.cshtml で指定されます

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

テスト Identity

既定の Web プロジェクト テンプレートでは、ホーム ページへの匿名アクセスが許可されます。 をテストするには Identity 、 を追加します [Authorize]

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

サインインしている場合は、サインアウトします。アプリを実行し、リンクを Privacy 選択します。 ログイン ページにリダイレクトされます。

Tsm Identity

詳細については、次を参照して Identity ください。

Identity コンポーネント

依存しているすべての Identity NuGet パッケージは、 ASP.NET Core 共有フレームワークに含まれています。

のプライマリパッケージ Identity はAspNetCore です Identity 。 このパッケージには、のインターフェイスのコアセットが含まれており、によって含まれてい ASP.NET Core Identity Microsoft.AspNetCore.Identity.EntityFrameworkCore ます。

移行先 ASP.NET Core Identity

既存のストアの移行に関する詳細とガイダンスについて Identity は、「認証と Identity の移行」を参照してください。

パスワードの強度を設定する

パスワードの最小要件を設定するサンプルについては、「 構成 」を参照してください。

AddDefault Identity と AddIdentity

AddDefaultIdentityは ASP.NET Core 2.1 で導入されました。 AddDefaultIdentityの呼び出しは、次の呼び出しに似ています。

詳細については、「 Adddefault Identity source 」を参照してください。

静的アセットの発行を禁止する Identity

静的 Identity アセット (UI 用のスタイルシートおよび JavaScript ファイル) を web ルートに発行できないようにするには Identity 、 ResolveStaticWebAssetsInputsDependsOn RemoveIdentityAssets アプリケーションのプロジェクトファイルに次のプロパティとターゲットを追加します。

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

次の手順