1. 程式人生 > >用例子看ASP.NET Core Identity是什麽?

用例子看ASP.NET Core Identity是什麽?

size 集合 base 登錄管理 false 路徑 ext side 多余

原文:用例子看ASP.NET Core Identity是什麽?

目錄

  • 前言
  • 基於聲明的認證(Claims-based Authentication)
    • Claim
  • 在ASP.NET Core Identity中是如何實現的
  • 類ClaimsPrincipal
  • 考察另外一個重要的類ClaimsIdentity
  • 在ASP.NET Core Identity中一同運行
  • 總結

@

前言

有三個重要的類Claim, ClaimsIdentity, ClaimsPrincipal,我們以一個持有合法證件的學生Bob做比方,ClaimsPrincipal就是持有證件的學生Bob,ClaimsIdentity就是學生Bob的證件駕照,Claim就是Bob駕照中的各種信息。
下邊就開始圍繞上邊這段話展開描述:

基於聲明的認證(Claims-based Authentication)

在開始學習標識管理系統(Identity system)之前,很有必要搞清楚什麽是基於聲明的身份認證。
我們假設一個場景。Bob是一名大學生,準備去銀行為自己開戶。銀行工作人員需要Bob提供他的有效證件,於是Bob就把自己的駕照提供給了銀行工作人員。銀行工作人員可以從駕照上獲取到Bob的個人信息,例如姓名、出生日期和地址等。
Bob希望能夠享受到銀行針對大學生的優惠政策,於是銀行工作人員又請Bob提供了學生證,同時從上邊可以獲取到姓名、所在的大學名稱、院系以及學號等信息。(這裏提供別人的學生證一定是不行的!)
使用以上生活中典型的應用場景,可以幫助我們進一步去理解基於聲明(Claims-based Authentication)的身份認證。這個例子中Bob擁有兩個標識(Identity,就相當於有效的身份證明,即證明你是你的那張紙,也就是Identity):駕照+學生證。(當然還可以提供更多的Identity,比如護照、戶口本等等。)
好吧,我自己用文字越寫越怕不明白,通過上邊的這些文字,只需要清楚這麽幾點內容:

Claim

  • 就是一個鍵值對,例如:name:Bob
  • Claim可以是姓名、出身日期、地址、所在大學、學號等等信息

    Identity

  • 很多條Claim組成了一個Identity
  • Identity就是一個有效的身份證明 = 證明你是你的那張紙 = 駕照、學生證等等
  • 一個人可以擁有很多個Identity

技術分享圖片
Bob去開戶,先提供了一個Identity(這裏就是駕照),接著又提供了一個Identity(學生證)

清楚了這些,我們繼續看

在ASP.NET Core Identity中是如何實現的

ASP.NET Core 是開源的,這能夠讓我們非常方便的去學習和理解它是如何構成並運行的。源碼可以去github上查看。
可以把源碼下載下來,然後查看源碼,路徑為:
corefx-master(解壓後主文件夾)/src/System.Security.Claims/src/System/Security
技術分享圖片

類ClaimsPrincipal

一個用戶(User)被聲明成ClaimsPrincipal類型(繼承自IPrincipal接口)。ClaimsPrincipal類來自System.Security.Claims命名空間。

public class ClaimsPrincipal : IPrincipal
{
    ...........
    ...........
    public virtual IIdentity Identity { get; }
    public virtual IEnumerable<ClaimsIdentity> Identities { get; }
    public virtual IEnumerable<Claim> Claims { get; }
    ...........
    ...........
    public virtual bool HasClaim(Predicate<Claim> match);
    public virtual bool HasClaim(string type, string value);
    public virtual bool IsInRole(string role);
    ...........
    ...........
}

從ClaimsPrincipal類中可以看到有一個返回類型為ClaimsIdentity集合的Identities屬性,代表著一個User可以擁有多個Identity。
在這裏的另外一個屬性Identity,不要被迷惑,他返回的是ClaimsPrincipal中主要的(如果有多個)那一個ClaimIdentity。
另外一個重要的屬性Claims,它返回了一個在ClaimsPrincipal中所有的ClaimsIdentity所包含得全部Claims的集合。

考察另外一個重要的類ClaimsIdentity

public class ClaimsIdentity : IIdentity
{
...........
...........
public virtual string AuthenticationType { get; }
public virtual string Name { get; }
public virtual bool IsAuthenticated { get; }
public virtual IEnumerable Claims { get; }
public virtual IEnumerable FindAll(Predicate match);
public virtual Claim FindFirst(string type);
public virtual bool HasClaim(string type, string value);
...........
...........
}

  • 這裏的AuthenticationType屬性從字面意思就能很好的理解,返回認證的類型,在本示例中就可能是駕照或者學生證。在ASP.NET Core 中也可能是例如:微信、QQ、Cookies、Basic、Windows、Google等等。用AuthenticationType來驗證和確定與身份相關聯的聲明用的什麽方法。
  • 還有一個IsAuthenticated屬性,用來獲取Identity是否被驗證,大家可能會感覺多余,在沒有通過驗證的時候又怎麽會得到一個擁有Claims的Identity呢?有一個典型應用場景就是,允許遊客訪問你的網站,允許使用購物車。這個遊客一樣擁有由聲明(Claims)組成的標識(Identity),只是這位遊客還沒有被驗證。這一非常重要的區別需要牢記。
    在ASP.NET Core 創建一個ClaimsIdentity的時候,IsAuthenticationType總會被初始化為true。一個通過驗證的用戶一定會是true,相反未被驗證的遊客,此屬性為false。
  • Claims是組成Identity的全部Claim集合。

現在我們把這個假設的應用場景用圖示再總結一下:
技術分享圖片

在ASP.NET Core Identity中一同運行

上述內容在ASP.NET Core Identity 中使用Identity對象的簡單交互已經創建了一些API,例如SignInManager, UserManager ,RoleManager等,在ASP.NET Core 項目中通過依賴註入就可以使用它們。
例如,登錄管理就通過下邊一個public方法來完成登錄:

public virtual async Task SignInAsync(TUser user, AuthenticationProperties authenticationProperties, 
string authenticationMethod = null)
{
    var userPrincipal = await CreateUserPrincipalAsync(user);
    if (authenticationMethod != null)
    {
        userPrincipal.Identities.First().AddClaim(new Claim
               (ClaimTypes.AuthenticationMethod, authenticationMethod));
    }
    await Context.SignInAsync(IdentityConstants.ApplicationScheme,
        userPrincipal,
        authenticationProperties ?? new AuthenticationProperties());
}

總結

  • Claim就是一個鍵值對,用來描述一個特新,比如姓名:Bob就是一個Claim,生日:2009.9.15這也是一個Claim。其中姓名或生日就是這個Claim的一種類型,即Claimtype。
  • 一組claim就構成了一個identity,具有這些claims的identity就是 ClaimsIdentity ,也可以把ClaimsIdentity理解為“證件”,駕照就是一種ClaimsIdentity,學生證也是一種ClaimIdentity。
  • ClaimsIdentity的持有者就是ClaimsPrincipal ,一個ClaimsPrincipal可以持有多個ClaimsIdentity,就比如Bob既持有駕照(ClaimIdentity),又持有身份證(ClaimIdentity)。
    理解了Claim, ClaimsIdentity, ClaimsPrincipal這三個概念,就能理解生成登錄Cookie為什麽要用下面的代碼?
...
var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, loginName) }, "Basic");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
await context.Authentication.SignInAsync(_cookieAuthOptions.AuthenticationScheme, claimsPrincipal);
...

要用Cookie代表一個通過驗證的主體,必須包含Claim, ClaimsIdentity, ClaimsPrincipal這三個信息,以一個持有合法駕照的人做比方,ClaimsPrincipal就是持有證件的人Bob,ClaimsIdentity就是證件駕照,"Basic"就是證件類型(這裏假設是駕照),Claim就是駕照中的信息。
如果感覺困擾,可以再看下dudu博客的這篇文章
這篇教程中,因為自己在理解的時候花了不少時間,請大家指證!

用例子看ASP.NET Core Identity是什麽?