ASP.NET Core 基于声明的访问控制到底是什么鬼?

时间:2022-07-25
本文章向大家介绍ASP.NET Core 基于声明的访问控制到底是什么鬼?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

从ASP.NET 4.x到ASP.NET Core,内置身份验证已从基于角色的访问控制(RBAC)转变为基于声明的访问控制(CBAC)

我们常用的HttpContext.User属性ASP.NET 4.0时代是IPrincipal类型,ASP.NETCore现在强化为ClaimsPrincipal类型。

本文就一起来看看这难缠的、晦涩难懂的声明式访问控制。

1.Claims : 声明

声明是基于声明的身份验证(claims-based authentication)的基础,声明是某主题(Subject)的片段信息

声明是个名词,并不能说明主体可以做什么或不能做什么, 对应现实生活中各种卡片上体现的片段信息。 使用术语“主题”是因为声明不仅限于描述用户,声明可能与应用程序,服务或设备有关。

主题

Claim1

Claim2

Claim3

Claim3

Claim5

Claim6

Claim7

Claim8

身份证

身份证号

姓名

性别

籍贯

生日

签发机关

签发时间

过期时间

工作狗牌

姓名

级别

花名

身份证号

性别

base地区

入职时间

---

王者荣耀

账号

游戏等级

大区

角色

氪金级别

年龄

注册时间

---

微信

微信号

昵称

注册时间

国籍

实名证件

手机号

---

---

车牌

车牌编号

车牌所属人

车牌地区

车牌性质

签发时间

签发机关

---

---

某大保健会员卡

卡号

姓名

手机号

会员级别

办卡时间

办卡门店

---

---

// 声明通过`System.Security.Claim`类表示
public class Claim {
  public string Type { get; }
  public string Value { get; }
  public string ValueType { get; }
  // some properties have been omitted.
}

对比可见:每个声明都有一个标识片段信息类型的Type属性、保存片段信息的Value属性、片段信息的数据类型。

var idClaim = new Claim(“Id”,“ 1”,“Integer”);        // 用户ID:整形
var dobClaim = new Claim(“dob”,“04/20/2000”,“Date”);  // 生日:事件类型
var emailClaim = new Claim(nameof(ClaimTypes.Name), mockUser.Email,nameof(ClaimValueTypes.String)),

2. Identities:身份

同一主题的声明组合在一起,称为ClaimsIdentity

对应现实生活中各种卡片:身份证、工作狗牌、车牌、大保健会员卡,均体现了某一个主题。

public class ClaimsIdentity {
  public string Name { get; }
  public IEnumerable<Claim> Claims { get; }
  public string AuthenticationType { get; }    // 保存使用的身份验证方法(Bearer、Basic)
  public bool IsAuthenticated { get; }
  // some properties have been omitted.
}

假设某WebAPI可通过其唯一ID和名称来识别用户。验证从用户收到的承载令牌(JWT等)后,我们可以创建ClaimsIdentity来表示它们:

ClaimsIdentity userIdentity = new ClaimsIdentity(
  new Claim[] {
    new Claim("Id", "1"),
    new Claim("Username", "Bert")
  },
  "Bearer"
);

//userIdentity.IsAuthenticated == true since we passed "Bearer" as AuthenticationType.

3. Principals: 主体

ClaimsIdentity可以方便地表示一个主题(一组声明),很多时候一个主体有多个身份,就像现实生活中我们有个身份卡片,这个时候我们就需要钱包或者账号管理工具(1Passwowd、LassPass),将各种身份集中在一起就是主体ClaimsPrincipal

接上面的例子, 如果WebAPI需要确保访客使用的设备处于白名单,则可以对访客维护设备身份

ClaimsIdentity deviceIdentity = new ClaimsIdentity(
  new Claim[] {
    new Claim("IP", "192.168.1.1"),
    new Claim("Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
  }
);
//  针对访客设备声明,不要设置AuthenticationType

主体对象代表代码运行的用户的安全上下文,是各种有效身份的组合。

public class ClaimsPrincipal {
  public IEnumerable<Claim> Claims { get; }
  public IEnumerable<ClaimsIdentity> { get; }
  public ClaimsIdentity Identity { get; }
  public virtual IEnumerable<Claim> FindAll(Predicate<Claim> match);
  public virtual bool HasClaim(string type, string value);
  // ClaimsPrincipal提供了一些辅助方法/属性来检查声明.
}

 var principal = new ClaimsPrincipal(new IIdentity[] { userIdentity, deviceIdentity });

总结

基于声明的身份验证是WebApp获取它们需要的组织内部、其他组织以及Internet上的用户的身份信息的常用方法。它还为本地或云中运行的应用程序提供了一致的方法。基于声明的身份验证将身份和访问控制的各个元素抽象为两个部分:声明的概念以及颁发者或授权机构的概念。[

  1. Claims: 身份信息的片段数据
  2. Identities:各种身份卡片
  3. Principals:主体,各种身份账户的集中存储地