.NET中Identity与Principal的区别

一、IIdentity

在.NET的安全应用编程接口中,身份通过System.Security.Principal.IIdentity接口表示。从下面表示IIdentity接口定义的代码片断中,我们可以看到这个接口定义其实很简单,它具有如下三个只读属性:

  • Name: 身份所代表的用户的名称;
  • IsAuthenticated: 身份所代表的用户是否经过认证;
  • AuthenticationType: 身份认证所采用的类型。

 

通过IIdentity表示的身份是基于某种认证类型的,不同类型的认证往往对应于不同的身份类型。以ASP.NET认证为例,如果我们采用Forms认证,那么认证后的身份通过一个FormsIdentity对象表示。而Windows Live Passport认证对应的具体身份类型则是PassportIdentity。在这里我们着重介绍一下如下三种身份类型:WindowsIdentity、GenericIdentity和X509Identity。

二、WindowsIdentity

WindowsIdentity定义在System.Security.Principal命名空间下。顾名思义,WindowsIdentity 用于表示一个基于Windows认证的身份。一个采用WindowsIdentity定义的Windos身份具有一系列的属性,它们主要定义在如下的代码 片断中。

 

对于用于表示认证类型的AuthenticationType属性来说,在工作组模式下返回NTLM。对于域模式,如果操作系统是Vista或者以 后的版本,该属性返回Negotiate,表示采用SPNEGO认证协议。而对于之前的Windows版本,则该属性值为Kerberos。

Groups属性返回WindowsIdentity对应的Windows帐号所在的用户组(User Group),而IsGuest则用于判断Windows帐号是否存在于Guest用户组中。IsSystem属性则表示Windows帐号是否是一个系统帐号。

如果你对ASP.NET的安全有一定的了解,应该知道我们可以对IIS进行相应的配置是ASP.NET应用支持匿名用户。也就是说,用户无需提供具 体的用户凭证,而是以匿名的方式登录到ASP.NET站点中。对于匿名登录,IIS实际上会采用一个预先指定的Windows帐号进行登录。而在这 里,IsAnonymous属性就表示该WindowsIdentity对应的Windows帐号是否是匿名帐号。

对于匿名身份的问题,在这里还有一点值得补充一下。WindowsIdentity定义了如下一个静态的GetAnonymous方法用于返回一个表示匿名身份的WindowsIdentity对象。但是这仅仅是一个空的WindowsIdentity对象而以 ,并不对应着某个确定的Windows帐号。

 

任何一个具体的Windows进程总是运行在一个确定的安全身份下。如果你手工启动一个.exe文件,被开启的进程会运行在基于当前登录帐号的身份 下。如有你同时拥有多个Windows帐号,你可以通过“Run As”的方式选择一个不同于当前登录帐号的身份去运行某个.exe文件。而对于很多的Windows服务,它们大多运行在某个系统帐号下。比如我们熟悉的 IIS(IIS6或者之后的版本)在默认的情况下就运行在Network Service这个系统帐号下面。当一个线程在这个进程中被创建并启动的时候,进程的安全身份会自动附加到线程上。WindowsIdentity为我们 提供了如下一个GetCurrent静态方法返回基于当前线程/进程的WindowsIdentity。

三、 GenericIdentity

虽然对于这些我们常用的认证类型,比如Windows认证、Forms认证和Windows Live Passport认证,都具有对应的安全身份类型。如果我们采用自定义的认证方式,是否意味着我们也需要定义一个实现了IIdentity接口的类型呢? 实际上是不需要的,我们可以直接使用GenericIdentity这个类型。

正如名称所体现的一样,GenericIdentity为我们定义了一个一般性的安全身份。GenericIdentity的定义非常简单,仅仅实 现了定义在IIdentity接口的三个只读属性而以。我们可以通过指定用户名或者用户名与认证类型来创建一个GenericIdentity对象。下面 的代码片断体现了GenericIdentity的整个定义。

 

由于GenericIdentity的IsAuthenticated属性是只读,也不同通过存储过程对其进行初始化,那么如何确定一个通过 GenericIdentity对象表示的安全身份是否已经通过认证了呢?实际上,GenericIdentity采用很简单的逻辑来判断其自身是否经过 认证:如果用户名不为空,IsAuthenticated返回True,否则返回False。下面给出的代码可以验证这一点。

 

四、X509Identity

通过前面一章的介绍,我们知道了WCF具有三种典型的认证方式:Windows认证、用户名/密码认证和证书认证。认证的方式决定了安全身份的类 型,对于Windows认证和用户名/密码认证,认证后的安全身份分别由一个WindowsIdentity和GenericIdentity表示。但是 对于证书认证,则对应着另一种安全身份类型:X509Identity。

X509Identity定义在程序集System.IdentityModel中,对应的命名空间是System.IdentityModel.Claims。从下面给出的定义我们可以看出X509Identity仅仅是一个内部 (Internal)类型。

 

X509Identity直接继承自GenericIdentity。我们可以通过传入一个X509Certificate2对象或者以 X500DistinguishedName对象表示的证书的标识名称来创建X509Identity。X509Identity重写了 GenericIdentity的Name属性,最终作为名称的返回的是证书的主题名称和指纹的组合,<<主题名称>>; <<指纹>> (分号之后具有一个空格,比如:CN=Foo; 12BA3675C89BD7FE00E3F7E92A620749FB9E6D89 )。X509Identity对象的AuthenticationType属性为“X509”。

五、服务安全上下文中的身份

当服务安全开始的情况,服务端在经过认证之后会创建一个上下文用以存储基于当前服务调用相关的安全相关的信息,其中就包含了代表被认证客户端的安全身份。这个上下文被称为服务安全上下文,通过类型ServiceSecurityContext表示。

 

你可以通过两种方式获取当前的ServiceSecurityContext,一种是通过ServiceSecurityContext的静态只读 属性Current,另一种则是通过当前OperationContext的ServiceSecurityContext属性。实际上通过这两种方式得 到的是同一个ServiceSecurityContext。ServiceSecurityContext对象的同一性可以通过下面的代码来验证。

 

ServiceSecurityContext具有两个表示安全身份的属性PrimaryIdentity和WindowsIdentity,它们都代表当前客户端的身份。对于Windows认证,这两个属性返回同一个WindowsIdentity对象 。不过需要注意的是,这是所说的Windows认证实际上包括如下三种情况:ThinkPHP集成FIREPHP

  • 客户端凭证为Windows凭证;
  • 客户端凭证为用户名/密码凭证,并采用Windows认证模式;
  • 客户端凭证为X.509证书凭证,并允许与Windows帐号进行映射。

而对于不属于上述三种情况下的非Windows凭证,当前ServiceSecurityContext的WindowsIdentity属性返回 Null,而PrimaryIdentity属性则因客户端凭证类型和认证方式有所区别。具体来说,如果客户端凭证为用户名/密码凭证,并采用 Membership和Custom认证模式,则在成功认证的情况下PrimaryIdentity的属性返回一个以用户名作为名称的 GenericIdentity。如果客户端凭证为X.509证书凭证,但不采用Windows帐号映射机制,则PrimaryIdentity的属性返 回的是一个X509Identity。

对于匿名客户端(客户端凭证类型为None),PrimaryIdentity返回的是一个空的 GenericIdentity,IsAnonymous返回True。你通过静态属性Anonymous可以返回一个匿名 ServiceSecurityContext。下满的表格体现了成功认证后当前ServiceSecurityContext的 PrimaryIdentity与客户端凭证类型以及认证模式之间的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值