共用方式為



2017 年 9 月

第 32 卷,第 9 期

本文章是由機器翻譯。

技術最前線 - ASP.NET Core 中的 Cookie、宣告與驗證

Dino Esposito | 2017 年 9 月

Dino Esposito大部分的文獻有關的驗證中 ASP.NET Core 佈景主題著重在 ASP.NET Identity framework 使用。在該情況下,作業似乎不完成或已變更大部分,更精確地說,所有基礎結構中發生的變更有已埋藏在摺疊的架構,使它看起來幾乎相同的介面上。

如果您看一下使用者驗證在 ASP.NET Core 外舒適領域的 ASP.NET 識別,您可能會發現它已在過去的版本與相當不同。ASP.NET Identity 是單純、 完整、 大的架構是大材小用,如果您只需要驗證使用者,透過簡單的資料庫資料表中的純文字認證。在此情況下,您會看到驗證的整體方法仍根據熟悉概念,例如: 主體、 登入表單、 挑戰和授權屬性不同之處在於您實作它們的方式就是完全不同。本月份的資料行中,我會在進行中 ASP.NET Core,包括核心事實的外部驗證提供探索 cookie 驗證應用程式開發介面。

ASP.NET 驗證的基礎

在 ASP.NET 中,使用者驗證牽涉到使用 cookie。如果它們不包含有效的驗證 cookie,任何使用者嘗試瀏覽私用的頁面會重新導向至登入頁面。登入] 頁面上,確認提供 creden tials 之後, 發出的 cookie,然後隨著後續的要求會從傳送該使用者已透過相同的瀏覽器直到過期為止。這是您可能知道從舊版本的 ASP.NET 的相同基本工作流程。在 ASP.NET Core,它只會尋找不同基於不同的中介軟體和執行階段環境不同的組態。

有兩個主要變更中 ASP.NET Core 對於來自 ASP.NET Web Form 和 ASP.NET MVC 的背景。首先,不再 web.config 檔案中,這表示該登入路徑,cookie 名稱的組態,並以不同的方式擷取到期日。其次,IPrincipal 物件 — 用來模型使用者識別的物件,現在會根據宣告,而不是單純的使用者名稱。若要啟用的 cookie 驗證中全新的 ASP.NET Core 1.x 應用程式,方法,您可以先參考 Microsoft.AspNetCore.Authentication.Cookies 封裝,然後再新增程式碼片段中的圖 1

圖 1 註冊的 Cookie 驗證中介軟體

// This code is for ASP.NET Core 1.x
public void Configure(IApplicationBuilder app)
{
  app.UseCookieAuthentication(new CookieAuthenticationOptions
  {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    AuthenticationScheme = "Cookies",
    CookieName = "YourAppCookieName",
    LoginPath = new PathString("/Account/Login"),
    ExpireTimeSpan = TimeSpan.FromMinutes(60),
    SlidingExpiration = true,
    ReturnUrlParameter = "original",
    AccessDeniedPath = new PathString("/Account/Denied")
  });
}

大部分的傳統儲存在 < > 的驗證一節的 web.config 檔案中的 ASP.NET MVC 應用程式會設定為中介軟體選項的資訊。在程式碼片段圖 1 comprehends 標準您可能想要選擇的選項。圖 2說明每個更多詳細資料。

圖 2 Cookie 驗證選項

屬性 描述
AccessDeniedPath 表示在經過驗證的使用者會被重新導向提供身分識別不需要檢視要求之資源的權限時的路徑。與取得以 HTTP 403 狀態碼相同。
AutomaticAuthenticate 指示中介軟體會在每個要求上執行並嘗試驗證 cookie 並建置身分識別物件的內容。
AutomaticChallenge 指示中介軟體瀏覽器重新導向至登入頁面。 是否使用者未經過驗證或存取遭拒頁面如果使用者已驗證,但未獲授權要求的資源上。 
AuthenticationScheme 中介軟體的名稱。這個屬性可搭配 AutomaticChallenge 選擇性地挑選每個要求為基礎的驗證中介軟體。
CookieName 正在建立的驗證 cookie 的名稱。
ExpireTimeSpan 設定驗證 cookie 的到期時間。是否適合做為絕對或相對時間取決於 SlidingExpiration 屬性的值。
LoginPath 表示重新導向至自己的認證登入,匿名使用者的路徑。
ReturnUrlParameter 用來傳遞原始要求導致重新導向至匿名使用者發生登入頁面的 URL 參數的名稱。
SlidingExpiration 指出 ExpireTimeSpan 值是否為絕對或相對的。在後者的情況下,值會被視為間隔中, 介軟體將會重新發出 cookie,如果半數以上的時間間隔已過。

請注意,路徑屬性不是字串類型。LoginPath AccessDeniedPath 屬於類型 PathString,其相較於純文字的字串類型,提供建置在要求 URL 時,發生正確逸出的狀況。

在 ASP.NET Core 的使用者驗證工作流程的整體設計可讓您靈活 bility 前所未有的數量。您可以在自訂各個層面。例如,我們來看看如何控制正以每個要求為基礎之驗證工作流程。

因應多種驗證配置

藉由將 AutomaticChallenge 設定為 false,您可以指示不到 [Authorize] 挑戰回應的每個形成値 (例如) 重新導向的中介軟體。如果沒有中介軟體將會處理挑戰會擲回例外狀況。自動挑戰舊版 ASP.NET 範數並沒有幾乎任何資訊,請參閱,您可以執行。

在 ASP.NET Core,您可以註冊多個與不同的驗證中介軟體的棋子,並判斷以演算法或透過設定要用於每個要求有哪個中介軟體。使用多個驗證中介軟體時,自動驗證可以在多個中介軟體,則為 true。AutomaticChallenge,而是,才應該啟用上零個或一個中介軟體。如需詳細資訊,請參閱bit.ly/2tS07Sm

驗證中介軟體的常見範例是以 cookie 為基礎的驗證、 承載驗證驗證透過社交網路,或身分識別伺服器,以及其他任何可以曾經想實作。假設您有下列的程式碼中設定的方法啟動類別:

app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
  AuthenticationScheme = "Cookies",
  LoginPath = new PathString("/Account/Login/"),
  AutomaticAuthenticate = true
});
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
  AuthenticationScheme = "Bearer",
  AutomaticAuthenticate = true 
}

請注意會取代 [Cookie] 等的 magic 字串只是為了限制錯字所使用的常數。特別是,可以取代字串"Cookie",如下所示:

AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme

請注意,UseIdentityServerAuthentication 不是 ASP.NET Core framework 的一部分,但屬於識別伺服器架構 (請參閱github.com/IdentityServer)。若要選擇每個要求為基礎的驗證配置中,,您可以使用新的屬性上的授權屬性在 ASP.NET MVC 中標示為受限於驗證和授權的動作:

[Authorize(ActiveAuthenticationSchemes = "Bearer")]
public class ApiController : Controller
{
  // Your API action methods here
  ...
}

結果的程式碼片段是通過驗證後所持有人權杖的範例 ApiController 類別的所有公用端點都必須使用者的識別。

模型化的使用者身分識別

在 ASP.NET 中,Isinrole 介面會定義可定義使用者識別的核心的軟體合約。登入的使用者是透過 HttpContext 控制器屬性的使用者屬性公開。IPrincipal 具有相同的實作中 ASP.NET 4.x (包括 ASP.NET MVC) 和 ASP.NET Core。不過,在 ASP.NET Core 預設主體物件無法 GenericPrincipal,但新 ClaimsPrincipal 型別。差別在於相關。

GenericPrincipal 共同構成索引鍵的某項使用者資訊-使用者名稱,即使在 cookie 中加密的驗證票證可以加入自訂使用者資料。多年來,變得太少的現代應用程式需求的唯一使用者名稱。使用者的角色,以及一些其他區塊的資訊,最明顯的圖片,且顯示名稱,出現絕對需要今天,強制執行每個實際的應用程式來建立每個與每個其專屬自訂主體類型或查詢使用者資訊使用使用者名稱做為索引鍵的要求。ClaimsPrincipal 只拔解決問題。

宣告是描述所登入使用者的屬性索引鍵/值組。屬性清單取決於應用程式,但包含名稱和最起碼的角色。宣告,換句話說,是模型識別資訊的 ASP.NET Core 方式。是否資料庫雲端或本機儲存體,甚至是硬式編碼,可以從任何來源,讀取宣告。宣告類別很簡單,這項目:

public class Claim
{
  public string Type { get; }
  public string Value { get; }
  
  // More properties ...
}

ASP.NET Core 的登入程序會經過三個類別:宣告、 ClaimIdentity 和 ClaimsPrincipal。
收集宣告清單會填入宣告物件的陣列的簡單方式:

public Claims[] LoadClaims(User user)
{
  var claims = new[]
  {
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.Role, user.Role),
    new Claim("Picture", user.Picture)
  };
  return claims;
}

宣告的名稱是一般的描述性名稱,轉譯為字串。不過,最常見的宣告類型均已分組為常數為 ClaimTypes 類別。在您建立的主體,才能呼叫完成的驗證工作流程之前, 您必須取得身分識別物件的保留:

var identity = new ClaimsIdentity(claims, "Password");

第一個引數是自助說明性-正在建立的身分識別相關聯的宣告清單。第二個引數是指的是驗證的身分識別所需的驗證配置的字串。字串"Password"是系統為使用者證明其識別身分所需要功能的提醒。字串 「 密碼 」 只是參考而非語法元素。

另一個有趣的層面的上一個範例是明確的使用者名稱不是絕對必要。任何宣告,無論宣告的型別,可以用來命名使用者。下列程式碼片段會顯示有新的身分識別物件的另一個對等的方法:

var identity = new ClaimsIdentity(claims,
  CookieAuthenticationDefaults.AuthenticationScheme,
  "Nickname",
  ClaimTypes.Role);

新的識別具有 [Cookie] 做為驗證配置和暱稱是用來提供使用者名稱提供的清單中宣告的名稱。角色,而是,判斷角色相同的清單中宣告的名稱。如果未指定,最後兩個參數預設為 ClaimTypes.Name 和 ClaimTypes.Role。最後,您會從身分識別建立主體。值得注意的是,不過,主體可能會有多個身分識別。如果聲音奇怪,將相同的應用程式的不同區域,可能需要不同資訊到相同的方式驗證使用者識別碼,才能在某些旅館桌子和進入電梯電子金鑰識別自己。ClaimsPrincipal 類別有一個身分識別的屬性 (集合) 和 Identity 屬性。後者是在集合中第一個項目參考。

外部驗證

ASP.NET Core 最多可支援透過從頭身分識別提供者的外部驗證。大部分的情況下,您的安裝適當的 NuGet 套件的工作。若要依賴 Twitter 驗證使用者,您可以納入 Microsoft.AspNetCore.Authentication.Twitter 封裝,並安裝相關中介軟體:

app.UseTwitterAuthentication(new TwitterOptions()
{
  AuthenticationScheme = "Twitter",
  SignInScheme = "Cookies",
  ConsumerKey = "...",
  ConsumerSecret = "..."
});

SignInScheme 屬性是將用來保存結果的身分識別的驗證中介軟體的識別項。在範例中,將使用的驗證 cookie。若要查看其效果,您會先加入 Twitter 呼叫控制器方法:

public async Task TwitterAuth()
{
  var props = new AuthenticationProperties
  {
    RedirectUri = "/"  
  };
  await HttpContext.Authentication.ChallengeAsync("Twitter", props);
}

接下來,一旦 Twitter 已經成功地驗證使用者,SignInScheme 屬性會指示在下一個應用程式。[Cookie] 的值是可接受,如果您想要從外部提供者 (在範例 Twitter) 所傳回的宣告的 cookie。如果您想要檢閱並完成透過說,以中繼格式的資訊,則必須中斷處理序在兩個簡介暫存的登入配置。除了標準的 cookie 中介軟體您具備下列項目:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
  AuthenticationScheme = "ExternalCookie",
  AutomaticAuthenticate = false
});
app.UseTwitterAuthentication(new TwitterOptions
{
  AuthenticationScheme = "Twitter",
  SignInScheme = "ExternalCookie"
});

當外部提供者傳回時,會使用 ExternalCookie 配置來建立暫存的 cookie。您有適當設定的重新導向路徑,有機會檢查 Twitter 所傳回的主體,並繼續編輯:

var props = new AuthenticationProperties
  RedirectUri = "/account/external"  
};

若要完成此工作流程還需要 cookie 配置中登入和登出暫存配置 (ExternalCookie):

public async Task<IActionResult> External()
  var principal = await HttpContext
    .Authentication
    .AuthenticateAsync("ExternalCookie");
  // Edit the principal
  ...

  await HttpContext.Authentication.SignInAsync("Cookies", principal);
  await HttpContext.Authentication.SignOutAsync("ExternalCookie ");
}

ExternalCookie,如 cookie,是只內部識別項,可以重新命名,因為它們會維持一致的應用程式。

總結

在 ASP.NET Core 許多項目看起來是完全不同,但最後的概念,您可能知道從 ASP.NET 的大部分仍會保持不變。您仍然必須先建立,驗證 cookie,您仍然可以控制 cookie 和到期日的名稱。外部驗證支援,且登入頁面會提供與之前相同的結構。不過,設定及驗證基礎結構的基礎工作會不同,同時保留其先前的彈性。

在本文中所述的所有項目是指 ASP.NET Core 1.x。有幾件事,將 ASP.NET Core 2.0 中運作方式不同。特別是,驗證中介軟體現在會公開為服務,並設定服務上必須設定:

services.AddCookieAuthentication(options =>
{
  Options.LoginPath = new PathString("/Account/Login"),
    options.AutomaticAuthenticate = true,
    options.AutomaticChallenge = true,
    options.AuthenticationScheme = "Cookies", 
    ...
});

在設定類別的方法啟動的 ASP.NET Core 2.0 應用程式,您只會宣告您打算使用的驗證服務,而不需要任何進一步的選項:

app.UseAuthentication();

也請注意,您用於程式碼中建立的驗證 cookie SignInAsync 方法也會公開從 HttpContext 物件直接管理,而不是適用於 ASP.NET Core 最後的程式碼片段所示,通過中間的 [驗證] 屬性1.x。


Dino Esposito 是作者"MICROSOFT.NET:架構的企業應用程式 」 (Microsoft Press,2014年) 和 「 使用 ASP.NET 的現代化 Web 應用程式 」 (Microsoft Press,2016年)。適用於.NET 和 JetBrains,在 Android 平台以及在產業活動全球技術推廣人員 Esposito 共用上的軟體的願景software2cents@wordpress.com和 Twitter 上: @despos

非常感謝下列 Microsoft 技術專家檢閱這篇文章:Chris Ross


MSDN Magazine 論壇中的這篇文章的討論