ASP.NETCoreIdentityなしでCookie認証を使用する

アプリ開発

公式サイトを見ながら試したのですが、なかなかに手こずったので、自分なりにやったことをまとめました。

スポンサーリンク

環境

  • Windows 11 Home 21H2
  • Visual Studio Community 2022
  • フレームワーク: .NET 6.0

手順

プロジェクト作成

今回は「ASP.NET Core Web アプリ」で作業していきます。

プロジェクトの作成

プロジェクト名や保存場所等はお好みで変えてください。今回は「WebApplication1」で説明していきます。

プロジェクトの構成
  • フレームワークは「.NET 6.0」を選択。
  • 認証なし、これからCookie認証を入れてくので余分なコードが無い方が楽。
  • Dockerにチェック入れましたが、どっちでもいいです。Docker使わなくても問題なし。
  • 一番下の「Do not use top-level statements」にチェック入れました。これは .NET 6.0 からの機能で、Main メソッドが隠蔽されるので、チェックを入れて隠蔽されない状態で始めていきます。
追加情報の設定

RazorPages 削除

Razorページは使わないので削除。CSHTML嫌い。

Razorページの削除

「Program.cs」内からも RazorPages処理を削除。

  • builder.Services.AddRazorPages();
  • app.MapRazorPages();
RazorPages処理の削除

Cookie認証の作成

Cookie認証するためのAPIを作成します。

「Controllers」フォルダーを作り、その中に「AccountController.cs」を作成します。

Controllerの作成

「AccountController.cs」に次のソースをコピペします。

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace WebApplication1.Controllers
{
    [AllowAnonymous]
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class AccountController : ControllerBase
    {
        [HttpGet]
        public ActionResult<string> GetUser()
        {
            var claims = HttpContext.User.Claims;
            var userId = claims?.FirstOrDefault(x => x.Type.Equals(ClaimTypes.Name))?.Value;
            return Ok(userId);
        }

        [HttpGet]
        public async Task<ActionResult> Login([FromQuery] string userId)
        {
            if (!userId.Equals("abc"))
            {
                return Unauthorized();
            }

            var claims = new List<Claim>() { new Claim(ClaimTypes.Name, userId) };
            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
            return Ok();
        }

        [HttpGet]
        public async Task<ActionResult> Logout()
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return Ok();
        }
    }
}

WEBページの作成

「wwwroot」フォルダーに「index.html」を作成し、

静的サイトの作成

「index.html」に次のコードをコピペします。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="login">ログイン</button>
    <button id="getUser">ユーザー情報取得</button>
    <button id="logout">ログアウト</button>
    <script>
        window.onload = function() {
            document.getElementById('login').onclick = function() {
                login();
            };
            document.getElementById('getUser').onclick = function() {
                getUser();
            };
            document.getElementById('logout').onclick = function() {
                logout();
            };
        };

        function login() {
            let xhr = new XMLHttpRequest;
            xhr.open('get', `/api/Account/Login?userId=abc`, true);
            xhr.send();
        }
        function getUser() {
            let xhr = new XMLHttpRequest;
            xhr.onreadystatechange = function () {
                if (this.readyState == 4 && this.status == 200) {
                    alert(this.responseText);
                }
            };
            xhr.open('get', "/api/Account/GetUser", true);
            xhr.send();
        }
        function logout() {
            let xhr = new XMLHttpRequest;
            xhr.open('get', "/api/Account/Logout", true);
            xhr.send();
        }
    </script>
</body>
</html>

Program.cs 修正

最後に「Program.cs」を修正します。

  • Cookie認証を有効化
  • APIコントローラーを有効化
  • 静的サイトを有効化
using Microsoft.AspNetCore.Authentication.Cookies;

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            builder.Services.AddControllers();
            builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
            builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            var app = builder.Build();
            if (!app.Environment.IsDevelopment()) {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.MapControllers();
            app.Run();
        }
    }
}

これで準備完了

実行

まず、Cookieが無いことを確認します。開発者ツールの「アプリケーション」タブを開き、左ツリーから Cookie を選択すると現在の Cookie が確認できます。

この状態で「ユーザー情報取得」ボタンを押しても何も返ってきません。

Cookie認証されていないことの確認

続いて、ログインボタンを押して、Cookie認証をします。Cookie が保存されたのが分かります。

Cookie認証したCookieの確認

Cookie認証をしたあと、ユーザー情報取得ボタンを押すと、認証したユーザーIDが表示されます。

認証したユーザーIDが取得できること

最後にログアウトをすると Cookie が削除され、ユーザー情報取得もできなくなります。

おわりに

今回のソースを GitHub に置きました。

参考

タイトルとURLをコピーしました