建立在您未使用 cookie 身份驗證登錄時重定向的機制 (ASP.NET Core 3.0)

更新頁 :
頁面創建日期 :

環境

Visual Studio
  • 可視化工作室社區 2019
ASP.NET酷
3.0 或更高版本

Cookie 身份驗證可以在 .NET Core 2.2 或更早版本中使用,但此提示在 .NET Core 3.0 及更高版本中提供專用代碼。

入門

這一次ASP.NET Core 使用 Cookie身份驗證作為登入身份驗證機制。 您可以認為 Cookie 身份驗證類似於傳統的表單身份驗證。

ASP.NET Core 身份驗證的其他機制是 ASP.NET 核心標識。 除了使用表單進行身份驗證外,您還可以使用 API 身份驗證、外部登錄服務、密碼管理和重置等。 您可以使用許多功能。 但是,從創建簡單的登錄螢幕的角度來看,這是一個有點誇張的身份驗證機制。 這次不使用它。

在 Cookie 身份驗證提示中,除非登錄,否則無法顯示登錄螢幕。 當您嘗試轉到其他螢幕時,您將被重定向到登錄螢幕。 登錄后,您還可以看到其他螢幕。

在登錄螢幕上輸入使用者名和密碼后,即可登錄。 使用者身份驗證本身是臨時實現的。 這一次,我們主要實現 Cookie 身份驗證,因此確定密碼是否正確等不是本質。

此提示部分列出了程式。 下載完整的程式的完整代碼。

建立項目

啟動 Visual Studio 並創建新專案。

image

選擇ASP.NET 核心 Web 應用程式

image

指定任何項目名稱和專案位置。

image

這一次,我們將使用MVC專案,但大多數其他範本都可以替換它。

對於身份驗證,請選擇"無身份驗證"。 如果選擇其他身份驗證,則使用 ASP.NET核心標識。

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;

您可以透過執行 AddAuthentation 和 AddCookie 方法啟用 Cookie 身份驗證。 如果不需要更改方案名稱,請指定 Cookie 身份驗證 Defaults.身份驗證 Scheme。

AddAuthorization 方法的選項。 如果為 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();
  });
}

向應用程式添加身份驗證功能,以便應用。 添加 UseAuthentation()。 描述位置根據 MSDN 文件應用。 放置在 UseAuthoriation() 之前。 否則,它仍為範本。

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?}");
  });
}

建立帳戶控制程式

創建創建登錄螢幕所需的控制器和操作。 將控制器名稱創建為「帳戶控制器」。 這是因為默認情況下,登錄螢幕的控制器和操作名稱設置為"*/帳戶/登錄"。 如果要更改此路徑,可以使用 Startup.cs中的 AddCookie 方法選項進行更改。 我們將使用預設設置前進。

image

首先,創建控制器的一側。 通過授予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();
}

按下登錄按鈕后的身份驗證過程。 如果使用者名和密碼匹配,則啟用身份驗證。

以下代碼是身份驗證所需的最低代碼,用於定義聲明、標識和 Pricinpal。 調用 HttpContext.SignInAsync 方法生成並經過身份驗證。

如果需要額外的聲明或 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));
}

建立檢視(登入表單)(/檢視/帳戶/登錄.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 身份驗證所需的最低實現。 運行並查看其工作原理。 您的行為應該取決於您是否登錄。 一個簡單的例子是,你可以檢查以下行為。

操作 = 動作結果
無需登錄即可回家 重定到登入螢幕
登入 將主畫面
註銷主頁,無需登錄即可回家 重定到登入螢幕
不要註銷主頁,無需登錄即可回家 將主畫面