asp.net identity 基础概念篇-理解什么是声明

在具体介绍使用方法前,我们需要先了解几个概念:

1,claim:英文翻译过来是声明的意思,一个claim包含Type,Value两项信息。我把claim理解成一个权限的定义,比如Type=会员,Value=删除操作

2,Identity:表示用户的身份信息,比如用户名

3,Principal:我理解成认证票据,里面包含identity,claim信息。

4,Policy:英文翻译过来是政策的意思,我理解的是权限验证的一个规则,就是当前我需要如何验证权限,比如要执行当前操作,必须具有会员删除操作的claim

5,角色:一组权限的集合

6,用户:一个使用系统的账户信息

理解什么是声明

声明(Claims)其实就是用户相关的一条一条信息的描述,这些信息包括用户的身份(如Name、Email、Country等)和角色成员,而且,它描述了这些信息的类型、值以及发布声明的认证方等。我们可以使用声明来实现基于声明的授权。声明可以从外部系统获得,当然也可以从本地用户数据库获取。

对于ASP.NET MVC应用程序,通过自定义AuthorizeAttribute,声明能够被灵活的用来对指定的Action 方法授权访问,不像传统的使用角色授权那么单一,基于声明的授权更加丰富和灵活,它允许使用用户信息来驱动授权访问。

既然声明(Claim)是一条关于用户信息的描述,最简单的方式来阐述什么是声明就是通过具体的例子来展示,这比抽象概念的讲解来的更有用。所以,我在示例项目中添加了一个名为Claims 的 Controller,它的定义如下所示:

  1. public class ClaimsController : Controller
  2. {
  3.     [Authorize]
  4.     public ActionResult Index()
  5.     {
  6.         ClaimsIdentity claimsIdentity = HttpContext.User.Identity as ClaimsIdentity;
  7.         if (claimsIdentity == null)
  8.         {
  9.             return View("Error", new string[] {"未找到声明"});
  10.         }
  11.         else
  12.         {
  13.             return View(claimsIdentity.Claims);
  14.         }
  15.     }
  16. }

在这个例子中可以看出ASP.NET Identity 已经很好的集成到ASP.NET 平台中,而HttpContext.User.Identity 属性返回一个 IIdentity 接口的实现,而当与ASP.NET Identity 结合使用时,返回的是ClaimsIdentity 对象。

ClaimsIdentity 类被定义在System.Security.Claims 名称空间下,它包含如下重要的成员:

Claims

返回用户包含的声明对象集合

AddClaim(claim)

为用户添加一个声明

AddClaims(claims)

为用户添加一系列声明

HasClaim(predicate)

判断是否包含声明,如果是,返回True

RemoveClaim(claim)

为用户移除声明

当然ClaimsIdentity 类还有更多的成员,但上述表描述的是在Web应用程序中使用频率很高的成员。在上述代码中,将HttpContext.User.Identity 转换为ClaimsIdentity 对象,并通过该对象的Claims 属性获取到用户相关的所有声明。

一个声明对象代表了用户的一条单独的信息数据,声明对象包含如下属性:

Issuer

返回提供声明的认证方名称

Subject

返回声明指向的ClaimIdentity 对象

Type

返回声明代表的信息类型

Value

返回声明代表的用户信息的值

有了对声明的基本概念,对上述代码的View进行修改,它呈现用户所有声明信息,相应的视图代码如下所示:

  1. @using System.Security.Claims
  2. @using Users.Infrastructure
  3. @model IEnumerable<Claim>
  4. @{
  5.     ViewBag.Title = "Index";
  6. }
  7. <div class="panel panel-primary">
  8.     <div class="panel-heading">
  9.         声明
  10.     </div>
  11.     <table class="table table-striped">
  12.         <tr>
  13.             <th>Subject</th>
  14.             <th>Issuer</th>
  15.             <th>Type</th>
  16.             <th>Value</th>
  17.         </tr>
  18.         @foreach (Claim claim in Model.OrderBy(x=>x.Type))
  19.         {
  20.             <tr>
  21.                 <td>@claim.Subject.Name</td>
  22.                 <td>@claim.Issuer</td>
  23.                 <td>@Html.ClaimType(claim.Type)</td>
  24.                 <td>@claim.Value</td>
  25.             </tr>
  26.         }
  27.     </table>
  28. </div>

Claim对象的Type属性返回URI Schema,这对于我们来说并不是特别有用,常见的被用来当作值的Schema定义在System.Security.Claims.ClaimType 类中,所以要使输出的内容可读性更强,我添加了一个HTML helper,它用来格式化Claim.Type 的值:

  1. public static MvcHtmlString ClaimType(this HtmlHelper html, string claimType)
  2. {
  3.     FieldInfo[] fields = typeof(ClaimTypes).GetFields();
  4.     foreach (FieldInfo field in fields)
  5.     {
  6.         if (field.GetValue(null).ToString() == claimType)
  7.         {
  8.             return new MvcHtmlString(field.Name);
  9.         }
  10.     }
  11.     return new MvcHtmlString(string.Format("{0}",
  12.     claimType.Split('/', '.').Last()));
  13. }

有了上述的基础设施代码后,我请求ClaimsController 下的Index Action时,显示用户关联的所有声明,如下所示:

asp.net identity 基础概念篇-理解什么是声明