2020-01-07 更新

ユーザー認証機能の実装

ASP.NET coreではユーザー認証の仕組みを自動で生成することができます。

簡単に認証機能を実装できるなら是非とも利用したいので、実際にプロジェクトを作成してどんなコードが生成されるのか確認してみました。

目次

  • 認証機能を実装したプロジェクトの作成
  • Startup.cs
  • appsettings.json
  • Data/ApplicationDbContext.cs
  • Models/ApplicationUser.cs
  • Views/Account/*
  • Controllers/AccountController.cs
  • 実際の画面
  • 最後に
  • 参考リンク

認証機能を実装したプロジェクトの作成

プロジェクト作成時に認証機能の有無を選択することができます。

プロジェクトの新規作成

ASP.NET Core Webアプリケーションを選択してOKを押し、テンプレート選択画面へ。

Web APIまたはWebアプリケーションを選択すると右側の「認証の変更」ボタンが操作可能になるので、押して認証機能の選択画面へ。

とりあえず今回は「個別のユーザーアカウント」を選択して、プロジェクトを作成してみます。

以下は、作成されたプロジェクト内の認証機能に関連するコードを一部抜粋したものです。

Startup.cs


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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseAuthentication();
    }
}

options.UseSqlServer()で認証で利用するSQLServerのDBを指定しています。

EntityFrameworkのコードファーストが前提となるようなので、個人的にはSQLServer以外でちゃんと動作するのか...という不安があります。

appsettings.json


{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication9-**********;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
}

デフォルトのDB接続文字列が「appsettings.json」に設定されています。

Data/ApplicationDbContext.cs


public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}

認証で利用するテーブル名の変更など、カスタマイズしたい場合に利用します。

Models/ApplicationUser.cs


public class ApplicationUser : IdentityUser
{
}

ユーザー情報で追加したいプロパティがあればここに追記します。

Views/Account/*

機能的に単純なログインだけでなく、ユーザーの登録や外部サービスでのログイン、2段階認証、パスワードを忘れた場合や登録時のメールアドレス確認など、必要と思われる機能が一通り搭載されている感じなので、用意されているビューのファイルも沢山あります。

Controllers/AccountController.cs

認証関連のコントローラー。とりあえずログイン(Login)とユーザー登録(Register)のみ抜粋。


[Authorize]
[Route("[controller]/[action]")]
public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public AccountController(
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
    {
        _userManager = userManager;
        _signInManager = signInManager;
    }

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> Login(string returnUrl = null)
    {
        await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in.");
                return RedirectToLocal(returnUrl);
            }
        }
        return View(model);
    }

    [HttpGet]
    [AllowAnonymous]
    public IActionResult Register(string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var result = await _userManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
                await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

                await _signInManager.SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
        }
        return View(model);
    }
}

実際の画面

作成されたプロジェクトを実行すると、右上にユーザーの登録とログインのリンクが配置されています。それぞれの画面は以下の通り。

ユーザーの登録

ログイン

最後に

とりあえずは個人で利用すると思いますので、こんなに立派な機能はいらないですね。必要なものだけに絞り込んで使ってみます。

参考リンク

ASP.NET Core】関連記事