쿠키 인증을 사용하여 로그인하지 않은 경우 리디렉션할 메커니즘 생성(ASP.NET Core 3.0)

페이지 업데이트 :
페이지 생성 날짜 :

환경

Visual Studio
  • Visual Studio Community 2019
ASP.NET Core
3.0 이상

Cookie 인증 .NET Core 2.2 또는 이전 버전에서 사용할 수 있지만, 당사 Tips에서 .NET Core 3.0 이상 전용 코드가 나와 있습니다.

처음에

이번에 ASP.NET Core로 로그인 인증 방식으로 Cookie 인증 을 사용 합니다. Cookie 인증은 기존의 폼 인증과 유사한 것 이라고 생각 하 고 있습니다.

ASP.NET Core의 인증 메커니즘으로 다른 ASP.NET Core Identity가 있습니다. 이것은 폼을 사용 하 여 인증 외에 API 인증 외부 로그인 서비스를 사용할 수 있고, 암호 관리 및 다시 설정 많은 기능을 사용할 수 있습니다. 그러나이 간단한 로그인 화면을 만드는 것 이라는 관점에서 보면 다소 과장 된 인증 방식 이기 때문에 이번에는 사용 하지 않습니다.

이번에 소개 하는 Cookie 인증 Tips에서 로그인 하지 않으면 로그인 화면만 볼 수 없고 다른 화면으로 이동 하려고 하면 로그인 화면으로 리디렉션됩니다. 로그인 하면 다른 화면을 표시할 수 있습니다.

일단 로그인 화면에서 사용자 이름과 암호를 입력 하면 로그인 할 수 있도록 되어 있지만, 사용자 인증 자체는 임시 보관소에서 구현 하 고 있습니다. 이번에는 어디까지 나 Cookie 인증 구현을 메인으로 합니다 암호 올바른지 등의 판정 처리에 대 한 본질과 하지 않습니다.

이 Tips 프로그램은 부분적으로 설명 하 고 있습니다. 전체 코드를 보려면 프로그램 세트를 다운로드 해 라.

프로젝트 만들기

Visual Studio를 시작한 다음 새 프로젝트를 만듭니다.

image

ASP.NET Core Web 응용 프로그램 을 선택 합니다.

image

프로젝트 이름과 위치를 지정 합니다.

image

이번에는 MVC 프로젝트를 사용 하지만 다른 템플릿에서도 대부분은 대체 가능 합니다.

인증을 위해 인증 없음 을 선택 하십시오. 다른 인증을 선택한 경우, ASP.NET Core Identity를 사용 하는 것입니다.

image

프로젝트를 만든 후 디버깅을 실행 하면 아래 화면이 나타납니다. 이 화면을 기반으로 프로그램을 만들어 나갈 것입니다.

image

Startup.cs의 편집

Startup.cs에 Cookie 인증에 필요한 정의를 추가 합니다. 네임 스페이스는 다음을 사용 합니다.

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

AddAuthentication 메서드와 AddCookie 메서드를 사용 하 여 Cookie 인증을 사용할 수 있습니다. 체계 이름은 특히 변경할 필요가 없는 경우 CookieAuthenticationDefaults.AuthenticationScheme를 지정 합니다.

AddAuthorization 메서드의 options. FallbackPolicy에 RequireAuthenticatedUser를 지정 하면 평점 기준: 컨트롤러, 액션에 인증 필수 정책을 적용할 수 있습니다. 로그인 화면이 아닌 인증 요구 하는 경우 코드를 줄이고 기재 실수를 막는 의미 에서도 유용한 방법입니다. 로그인 화면만 별도 인증 불필요 한 코드를 작성할 수 있습니다.

public void ConfigureServices(IServiceCollection services)
{
  services.AddControllersWithViews();
  
  // Cookie による認証スキームを追加する
  services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();
  
  services.AddAuthorization(options =>
  {
    // AllowAnonymous 属性が指定されていないすべての Action などに対してユーザー認証が必要となる
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
      .RequireAuthenticatedUser()
      .Build();
  });
}

응용 프로그램에 인증 기능을 추가 하기 때문에 app. UseAuthentication () 를 추가 합니다. 설명 위치는 MSDN 설명서에 따라서 app. UseAuthorization ()의 앞에 배치 합니다. 그렇지 않으면 서식 파일에 남아 있습니다.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }
  else
  {
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. ...
    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?}");
  });
}

AccountController 만들기

로그인 화면을 만드는 데 필요한 컨트롤러와 작업을 만듭니다. 컨트롤러 이름은 「 AccountController 」로 만듭니다. 이것은 기본적으로 로그인 화면 컨트롤러 이름과 작업 이름을 「 ~/Account/Login 」 라고 정해져 있기 때문입니다. 이 경로를 변경 하려는 경우 Startup.cs의 AddCookie 메서드를 선택적으로 변경할 수 있습니다. 여기에는 기본 설정으로 진행 해 나갑니다.

image

우선은 Controller 쪽을 만듭니다. AllowAnonymous 특성을 부여 함으로써, 모든 작업은 인증 하지 않고도 실행할 수 있습니다. 그러면 로그인 화면만 인증 없이 액세스할 수 있습니다.

AllowAnonymous 특성이 로그인 화면 외 이용 장소로는 Cookie 인증 및 비관련 API 전용 컨트롤러 에서도 사용할 수 있습니다.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;

namespace CookieAuthentication.Controllers
{
  /// <remarks>
  /// <see cref="AllowAnonymous"/> 属性は Cookie 認証していなくてもアクセスできる Action (Controller) であることを示す。
  /// </remarks>
  [AllowAnonymous]
  public class AccountController : Controller
  {
  }
}

로그인 할 사용자 및 암호를 정의 합니다. 기본적으로 데이터베이스에 저장할 수 있지만, 이번 사용자 확인은 주목적이 아니기 때문에 임시 보관소에 세워 둡니다.

/// <summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; }

public AccountController()
{
  // 仮のユーザーを登録する
  UserAccounts = new Dictionary<string, string>
  {
    { "user1", "password1" },
    { "user2", "password2" },
  };
}

로그인 화면을 표시 하는 동작입니다. 표시 하기만 하면 되기 때문에 뷰를 반환 합니다.

/// <summary>ログイン画面を表示します。</summary>
public IActionResult Login()
{
  return View();
}

로그인 버튼을 누르면 인증 과정입니다. 사용자 이름과 암호가 일치 하는 경우 인증 가능 합니다.

다음 코드는 인증에 필요한 최소 코드 Claim, Identity, Pricinpal를 정의 하 고 HttpContext.SignInAsync 메서드를 호출 하 여 Cookie가 생성 되 고 인증 된 것입니다.

클레임이 추가 하거나 Cookie의 유효 기간이 필요한 경우 매개 변수를 추가 합니다.

로그인 후 인증 필수 ~/Home/Index에 리디렉션할 수 있습니다.

/// <summary>ログイン処理を実行します。</summary>
[HttpPost]
public async Task<IActionResult> Login(string userName, string password)
{
  // ユーザーの存在チェックとパスワードチェック (仮実装)
  // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
  if (UserAccounts.TryGetValue(userName, out string getPass) == false || password != getPass)
  {
    return View();
  }

  // サインインに必要なプリンシパルを作る
  var claims = new[] { new Claim(ClaimTypes.Name, userName) };
  var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync(principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToAction(nameof(HomeController.Index), "Home");
}

로그 아웃 처리를 켭니다. HttpContext.SignOutAsync 메서드를 호출 해 서 Cookie를 삭제 하 고 로그인 하지 않은 상태로 되돌릴 수 있습니다.

/// <summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
  // 認証クッキーをレスポンスから削除
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

  // ログイン画面にリダイレクト
  return RedirectToAction(nameof(Login));
}

보기 (로그인 폼) 만들기 (/Views/Account/Login.cshtml)

외형은 특히 고려 하지 않기 때문에 아래와 같이 사용자 이름과 암호를 입력 하는 입력란을 추가 하 고 로그인 버튼을 배치 합니다. 테스트용으로 로그인 하지 않고 Home/Index에 액세스 링크를 배치 합니다.

사용자 이름과 암호 입력이 귀 찮 아서 초기 값을 설정 합니다.

image

@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Login</title>
</head>
<body>
  <form method="post">
    <input name="userName" type="text" placeholder="ユーザー名" value="user1" />
    <input name="password" type="password" placeholder="パスワード" value="password1" />
    <button type="submit">ログイン</button>
  </form>
  <p><a asp-controller="Home" asp-action="Index">認証が必要な画面へ直接リンク</a></p>
</body>
</html>

로그 아웃 링크 만들기 (/Views/Shared/_Layout .cshtml)

홈 화면은 특히 변화 하지 않지만 탐색 모음에서 로그 아웃 링크를 붙여 둡니다. 또한 테스트 목적으로 로그 아웃 하지 않고 로그인 화면으로 전환 되는 링크를 붙여 둡니다.

image

<!-- 中略 -->
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
  <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </li>
    <!-- ここから追加 -->
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">Logout</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Login">ログアウトせずログインへ</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

동작 확인

이 Cookie 인증에 필요한 최소한의 구현을 완료 했습니다. 실행 하 고 동작을 확인 하 여 보시기 바랍니다. 로그인 하는지 하지 않는지에 따라 변화 하는 것입니다. 간단한 예로는 다음과 같은 동작을 확인할 수 있다고 생각 합니다.

작업 동작 결과
로그인 하지 않고 홈으로 로그인 화면에 리디렉션
로그인 홈 화면에
홈에서 로그 아웃 했다가 로그인 없이 홈으로 로그인 화면에 리디렉션
홈에서 로그 아웃 하지 않고 로그인 없이 홈으로 홈 화면에