用例子看ASP.NET Core Identity是什么?
网络安全 网络
原文:用例子看ASP.NETCoreIdentity是什么?目录前言基于声明的认证(Claims-basedAuthentication)Claim在ASP.NETCoreIdentity中是如何实现的类ClaimsPrincipal考察另外一个重要的类ClaimsIdentity@前言有三个重要的类Claim,ClaimsIdentity,ClaimsPrincipal,我们以一个持有合法证件…
原文:用例子看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

/upload/image/201908/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RoYW5rc2V2ZXJ5ZGF5,size_16,color_FFFFFF,t_70 alt="在这里插入图片描述">
Bob去开户,先提供了一个Identity(这里就是驾照),接着又提供了一个Identity(学生证)

清楚了这些,我们继续看

在ASP.NET Core Identity中是如何实现的

ASP.NET Core 是开源的,这能够让我们非常方便的去学习和理解它是如何构成并运行的。源码可以去github上查看
可以把源码下载下来,然后查看源码,路径为:
corefx-master(解压后主文件夹)/src/System.Security.Claims/src/System/Security
/upload/image/201908/2019031208034573.png alt="在这里插入图片描述">

类ClaimsPrincipal

一个用户(User)被声明成ClaimsPrincipal类型(继承自IPrincipal接口)。ClaimsPrincipal类来自System.Security.Claims命名空间。

public class ClaimsPrincipal : IPrincipal
{
    ...........
    ...........
    public virtual IIdentity Identity { get; }
    public virtual IEnumerable Identities { get; }
    public virtual IEnumerable Claims { get; }
    ...........
    ...........
    public virtual bool HasClaim(Predicate 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返回认证的类型,例如:Basic、Windows、Cookie等等。
Claims是组成Identity的全部Claim集合。
现在我们把这个场景用图示再总结一下:
/upload/image/201908/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RoYW5rc2V2ZXJ5ZGF5,size_16,color_FFFFFF,t_70 alt="在这里插入图片描述">

在这里再总结一下:

  • 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博客的这篇文章
这篇教程中,语言啰嗦之处还请见谅指证,因为自己在理解的时候花了不少时间,就怕解释不清说不清!