在具体介绍使用方法前,我们需要先了解几个概念:
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,它的定义如下所示:
-
public class ClaimsController : Controller
-
{
-
[Authorize]
-
public ActionResult Index()
-
{
-
ClaimsIdentity claimsIdentity = HttpContext.User.Identity as ClaimsIdentity;
-
if (claimsIdentity == null)
-
{
-
return View("Error", new string[] {"未找到声明"});
-
}
-
else
-
{
-
return View(claimsIdentity.Claims);
-
}
-
}
-
}
在这个例子中可以看出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进行修改,它呈现用户所有声明信息,相应的视图代码如下所示:
-
@using System.Security.Claims
-
@using Users.Infrastructure
-
@model IEnumerable<Claim>
-
@{
-
ViewBag.Title = "Index";
-
}
-
<div class="panel panel-primary">
-
<div class="panel-heading">
-
声明
-
</div>
-
<table class="table table-striped">
-
<tr>
-
<th>Subject</th>
-
<th>Issuer</th>
-
<th>Type</th>
-
<th>Value</th>
-
</tr>
-
@foreach (Claim claim in Model.OrderBy(x=>x.Type))
-
{
-
<tr>
-
<td>@claim.Subject.Name</td>
-
<td>@claim.Issuer</td>
-
<td>@Html.ClaimType(claim.Type)</td>
-
<td>@claim.Value</td>
-
</tr>
-
}
-
</table>
-
</div>
Claim对象的Type属性返回URI Schema,这对于我们来说并不是特别有用,常见的被用来当作值的Schema定义在System.Security.Claims.ClaimType 类中,所以要使输出的内容可读性更强,我添加了一个HTML helper,它用来格式化Claim.Type 的值:
-
public static MvcHtmlString ClaimType(this HtmlHelper html, string claimType)
-
{
-
FieldInfo[] fields = typeof(ClaimTypes).GetFields();
-
foreach (FieldInfo field in fields)
-
{
-
if (field.GetValue(null).ToString() == claimType)
-
{
-
return new MvcHtmlString(field.Name);
-
}
-
}
-
return new MvcHtmlString(string.Format("{0}",
-
claimType.Split('/', '.').Last()));
-
}
有了上述的基础设施代码后,我请求ClaimsController 下的Index Action时,显示用户关联的所有声明,如下所示: