《Windows Azure Platform 系列文章目录》
在我们介绍整套系统架构之前,我们需要首先定义一些基本的概念。
- 用户及其属性: 用户值得是要使用某项服务的个体。用户一般都有一系列与之相关的属性,例如用户名、用户的角色、用户的邮件地址等。
- 声明(Claim): 声明就是对某个个体的某项属性的一个确定的陈述。例如,"这位是张先生"就是对一个个体(一个人)的名称属性做出的一个断言--该人的名称属性值为"张先生"。任何个人都可以发表声明,比如笔者说"我姓白"就是笔者对自身姓属性的一个断言(assertion);而笔者身份证上印的名字就是由第三方(比如*局)对笔者姓名属性的一个断言。
- 安全令牌(Security Token):安全令牌是声明的集合。安全令牌一般都是经过签名(singature)和加密(encryption)的操作以确保信息的完整性、真实性、保密性和其自身不可仿制的特性。
- 服务提供方(Service Provider, SP)/依赖方(Relying Party, RP):服务提供方在这里指的就是要被访问的服务。注意服务提供方指的不是开发商,而是服务自身。在基于声明的体系架构下,服务提供方通常被称为"依赖方",用以表明它依赖于第三方提供验证和授权的事实。
- 身份提供方(Identity Provider):身份提供方是提供用户验证、发放安全令牌的服务。服务提供方依赖其信任的身份提供方来进行用户的身份验证,并根据身份提供方所提供的声明(包含在安全令牌中)来对用户进行授权。身份提供方和服务提供方之间的交互有若干种业界比较流行的协议,例如ws-Federation, SAML, Open ID Connect等。在本书中我们接触到的协议主要是ws-Federation。
- 信任(Trust):所谓信任指的是服务提供方和身份提供方之间的信任关系。一个服务提供方可以信任多个身份提供方,一个身份提供方也可以信任多个服务提供方。信任关系必须是相互的,单方面的信任是不成立的。所有相互信任的参与方共同组成了一个信任圈(Circle of Trust)。在这个信任圈内可以实现所谓单点登录(SSO)的功能,也就是说用户只需要在身份提供方登陆一次,就可以成功访问与身份提供方相互信任的服务提供方。
- 验证(Authentication):验证是确认个体属性的过程。例如,对用户的验证可能包括确认用户的名称属性、角色属性、邮件地址属性等。验证的过程通常需要被验证的个体提供某种身份证明,例如提供密钥、数字证书等。有的服务提供方还需要个体提供多种的验证方式,也就是人们所说的多重验证(Multi-factor Authentication)过程。相反,如果某个服务不需要对用户进行任何认证,我们也称这个服务允许匿名访问(Anonymous Access)。
- 授权(Authorization):授权是确认个体是否有请求某项服务的权限。授权的决定通常是根据个体的某些属性来决定。例如,有些网站的管理界面需要用户的角色属性必须是"管理员"才能访问。注意验证和授权是两个不同的概念。验证解决的是"你是谁"的问题,而授权解决的是"允许你做什么"的问题。
在定义了这些基本概念之后,我们就可以讨论基于声明的认证和授权的基本流程了。
1. 基本流程
基于声明的认证和授权过程一般有三个参与方:用户、服务提供方(或称依赖方)和身份提供方。其中,服务方将用户的认证交给身份提供商,并根据身份提供商所提供的声明来对用户进行授权。整个流程如下:
- 用户请求访问服务提供方所提供的服务,例如请求打开某个网页。
- 服务提供方发现用户尚未提供验证,就将用户转到其信任的身份提供方进行验证。
- 用户向身份提供方提供所需的证据以完成验证。验证完成后,身份提供方将用户的属性以声明的方式打包在一个安全令牌中返回给用户。
- 用户再次向服务提供方发出请求,并在请求中附上其从身份提供方所获得的安全令牌。
- 服务提供方对安全令牌进行验证。如果安全令牌验证通过,服务提供方就可以提取声明中的属性值。
- 服务提供方根据这些属性值来授权或拒绝用户的请求。
2.身份验证协议与WIF
上述流程是如何实现的呢?在过去数十年中,人们已经为身份验证过程中各方的交流方法、数据格式以及安全机制等设计了不同的身份验证协议(Protocol),比较流程的包括SAML, ws-Federation, OpenID,以及Windows上的Kerberos,NTLM等。尽管这些协议被广泛使用,但要想充分理解并掌握这些协议的细节需要大量的时间和精力。这无疑是大多数开发者所不愿意接受的。微软的Windows Identity Foundation (WIF)对不同的协议进行了大量的封装,并提供了非常简单的编程模式。基本上您不需要了解这些协议的任何细节也可以写出符合协议规范的代码。而在需要的时候您有可以挖掘到更深层次进行各种定制和扩展。在本章随后的实例中我们将看到WIF是如何简化身份验证编程的。随着.NET 4.5的发布,基于声明的身份验证已经深深嵌入到.NET底层。很多WIF中的类已经进入到了System命名空间,由这些方面足基于声明的身份验证已经成为.NET平台上最为基本的身份验证方式。
3.身份验证代理
上面介绍的只是一个基本流程。在一些更复杂的流程中还会有身份验证代理(Authentication Broker)的出现。身份验证代理作为身份提供方和服务提供方之间的中间人提供了几个重要的功能:
- 简化服务提供的开发和维护。身份验证代理可以隐藏与身份提供方交流的细节。服务提供方仅需与身份验证代理交流,就可以通过其服务连接到不同种类的身份提供方。
- 允许服务方同时支持多个身份提供方。通过身份验证代理所提供的身份提供方选择功能,一个服务可以允许用户以自己喜欢的方式登陆。
- 某些情况下,身份验证代理可以对身份提供方所提供的声明进行修改,例如增加或过滤声明、修改声明内容等。这样,即使身份提供方不能提供服务提供方所需要所需要的声明,也可以通过身份验证代理来修改这些声明以满足服务提供方的需求。
下面介绍有身份验证代理来修改这些声明以满足服务提供方的需求。
- 用户请求访问服务提供方所提供的服务,例如请求打开某个网页。
- 服务提供方发现用户尚未经过验证,就将用户转到其信任的身份提供方进行验证。在这里,服务提供方所信任的身份提供方是身份验证代理。
- [可选]如果服务提供方同时信任多个身份提供方,身份验证代理允许客户选择具体使用哪个身份提供方。这个过程称为Home Realm Directory。例如,身份验证代理可以提供一个网页,上面列有所有身份提供方的链接供用户选择;有的身份代理也可以根据用户名格式(例如邮件作为用户名时,邮件的域名)自动发现用户所使用的身份提供方。
- 在用户选择身份提供方后,身份验证代理将用户转到对应的身份提供方进行身份验证。注意身份验证代理本身并不进行身份验证。在这里,身份验证代理服务实际上是以服务提供方(或者依赖方)的身份来向身份提供方来所求安全令牌的。
- 用户向身份提供方提供所需的证据以完成验证。验证完成后,身份提供方将用户的属性以声明的方式打包在一个安全令牌中返回给身份验证代理。
- 身份验证代理对安全令牌进行必要的验证。根据系统配置,身份验证代理也可能对安全令牌中的生命进行修改、过滤或补充。
- 随后,身份验证代理将修改过的声明打包为新的安全令牌返回给客户。
- 用户再次向服务提供方发出请求,并在请求中附上其从身份验证代理所获得的安全令牌。
- 服务提供方对安全令牌进行验证。如果安全令牌验证通过,服务提供方就可以提取声明中的属性值。
- 服务提供方根据这些属性值来授权或拒绝用户的请求。
现实生活中的身份验证和授权
基于声明的身份验证和授权实际上和我们生活中常碰到的一些验证和授权的场景有很多相似之处。例如,当您乘坐飞机的时候,首先需要向工作人员出示身份证件以验证您的身份。这个身份证件实际上就是服务提供方(航空公司)所信任的身份提供方(*局)发放的一个安全令牌(身份证)。然后,工作人员根据您身份证上的信息来确认您的姓名(声明)。在这里,航空公司本身并没有对您的身份进行调查,而是相信您所提供的身份证(安全令牌)是真实的。当然,身份证是可以伪造的。航空公司选择信任身份证作为安排令牌是基于在绝大数情况下身份证是真实的这个事实。在计算机系统中,安全令牌的真实性一般是通过数字签名证书签名来确认的。
当工作人员完成身份证的检查(安全令牌验证)后,会向您发放登机牌(新的安排令牌)。登机牌上除了您的姓名(声明),还加上了您的座位号(声明)。在这种意义下上,柜台的工作人员也就是身份验证的一个代理。
在您登机的时候,登机口的服务人员检查您新获得的令牌(登机牌)并允许您登机(允许访问)。在登机后,您可以根据座位号到指定的座位——也就是您有使用该座位的授权。
在这里,笔者对身份验证和授权的过程只是进行了简略的介绍。对于绝大多数开发人员来说,理解到这种程度就已经足够了——毕竟基于声明验证机制的宗旨就是将开发人员从底层安全协议的处理中解放出来而专注于业务逻辑的开发。根据笔者的经验,在事实基于声明的身份验证时,最重要的就是保持对各个系统之前相互关系的一个清醒认识,并循序渐进对相关系统来逐一配置。这是因为各个系统之间的配置必须完全吻合才能正常运作,有时候一个细小的错误就会导致整个流程的失败。读者在配置和调试的过程中,特别是在定制的过程中一定要有些耐心,采用逐一修改配置逐一验证的方法,避免一次性修改多个配置。
参考文档:
《Windows Azure实战》——(美)白海石,机械工业出版社