代码改变世界

(翻译)《介绍 GENEVA Beta 1 白皮书》(2)

2009-06-03 17:21 by G yc {Son of VB.NET}, ... 阅读, ... 评论, 收藏, 编辑

有任何问题,可以查看 翻译预告 《介绍 GENEVA Beta 1 白皮书》或者直接在这里回复。

APPLYING CLAIMS-BASED IDENTITY AND “GENEVA”
应用 基于声明的标识(Claims-Based Identity) 和 “Geneva”

 

想要实现 基于声明的标识(Claims-Based Identity) 有关的想法就需要了解这个技术的基础。因此,最好的学习方式还是 通过 如何应用它 的示例来掌握。因此,本节将看几个关于这个技术的不同使用方式。

如果没有 基于声明的标识(Claims-Based Identity),应用程序开发者将面临各种情况,每个情况都有自己的 标识解决方案(Identity Solution)。 基于声明的标识(Claims-Based Identity)最大的 好处是使这些问题化解成一个问题: 如何使应用程序从信任的源那里获取用户信息? 正如本节说明的,基于声明的标识提供程序(Claims-Based Identity Provides) 为这些情形提供了一种统一的解决方式。

需要强调的是,虽然这些示例展示的是微软的技术,但是不使用他们也是没有问题的。其他供应商提供的产品,如 IBM的Tivoli Federated Identity Manager,也是提供STS 。类似的,其他的 身份选择器(Identity Selector)也是可用的,例如开源的 Higgins ,也可以用其他的类库来创建具有 声明意识(Claims-aware) 的应用程序。 关键的一点是,微软也是一个参与者,向着 基于声明的标识(Claims-Based Identity) 广泛的使用和多个供应商 而努力着。

 

USING CLAIMS INSIDE AN ENTERPRISE
在企业内部使用声明(Claim)

 

做为每个企业的 标识提供程序(Identity Provider),几乎为企业中的每个应用程序处理身份(Identity)。 “Geneva” 服务器,CardSpace “Geneva”,还有 “Geneva” Framework 都可以提供让运行在企业内部的应用程序使用 基于声明的标识(Claims-Based Identity) 的能力。图7显示了它的样子。

clip_image001[18]

图7: 使用的 ADDS 的企业, “Geneva” 服务器,CardSpace “Geneva”,还有 “Geneva” Framework 为内部应用程序 提供 基于声明的标识(Claims-Based Identity)的支持。

在这个例子中,用户使用ADDS登录,并获取最初的 Kerberos 票据(步骤1)。 然后,用户就可以访问使用 “Geneva” Framework 创建的具有 声明意识(Claims-aware) 的应用程序,并获取应用程序接受令牌(Token)的种类 和令牌(Token)中必须包含的声明(Claims)(步骤2)。如果使用了CardSpace “Geneva”(不是必须的,还记得吗?),用户将会看到先前图6 的画面,然后通过选择一个卡片来选择身份(Identity)(步骤3)。CardSpace “Geneva” 将会为这个身份(Identity)请求令牌(Token),并提供Kerberos 票据 来验证用户(步骤4)。 “Geneva” 服务器 STS 验证 票据(Ticket),然后 查找ADDS 获取用来创建请求令牌(Token)的信息(步骤5)。 令牌(Token)中所包含的声明(Claims)是根据 用户请求的信息和用户要访问的应用程序而决定的,每个应用程序都会明确的指出它所需要的声明(Claims)。一旦令牌(Token)成功创建,“Geneva”服务器 STS 会将它发送回到用户的系统(步骤6),然后 会发送它到应用程序(步骤7)。 应用程序使用 “Geneva” Framework 来验证 令牌(Token)的签名并使声明(Claims)可供使用(步骤8)。

基于声明的(Claims-Based )方法的一个很大的好处值得再次强调: 应用程序不需要再去查找自己需要的用户信息,相对的应用程序可以在令牌(Token)中得到传递给它的任何信息。 如果应用程序需要,比如,用户的职称(Job Title),它可以指定这个到它的需要的声明(Claims)列表中。当STS 为应用程序创建令牌(Token)的时候,它会 在ADDS 中寻找用户的职称(Job Title),并将它作为声明(Claim)插入到令牌(Token)中,然后应用程序就可以使用了。如果没有这个,应用程序的开发人员必须自己编写代码来在ADDS中搜索信息。基于声明的标识(Claims-Based Identity) 可以使开发人员的工作变得简单。

与简化开发人员的工作同时,STS也执行另一个功能:做为 声明转换器(Claims Transformer)。 例如,在图7中, 当客户端 向 “Geneva”服务器请求令牌(Token)时,提供了一个 Kerberos 票据。这个票据可能会影响 令牌(Token)中包含的简单一组声明(如用户的名字和成员组)。“Geneva”服务器 STS 使用这个令牌(Token)来验证用户发出的请求,然后发送另一个令牌(Token)。 这个新的令牌(Token)使用不同的格式——它是SAML令牌(Token)而不是Kerberos票据 ——并且 它可能包含一组不同的声明(Claims),因为它包含 目标程序指定的 任何东西。 你能非常真实的体会到了STS 转换了一组声明(Claims)到另一组中。

 

USING CLAIMS ON THE INTERNET
在互联网上使用声明(Claim)

 

现在假设这个组织希望同一个程序可以让外部雇员通过互联网访问进来。不用像传统的解决方案那样修改应用程序来接受 用户名/密码 的登录,同样的可以使用 基于声明的(Claims-Based )方法——应用程序不需要修改。图8 说明了这种情况。

clip_image001[20]

图8: 企业可以使用“Geneva” 服务器 STS 来为 在互联网上的用户创建令牌(Token)

这里,用户在使用另一台在企业外部的机器。与之前一样,该用户访问应用程序并获取它所接受的令牌(Token)类型(步骤1)。使用CardSpace(有用的但不是必须的),用户选择一个满足这些要求的标识(Identity)(步骤2)。然后,用户的系统 为这个标识(Identity)获取令牌(Token),从 使用“Geneva” 服务器 实现的企业的STS 那里(步骤3)。 然后,可以提交这个令牌(Token)到应用程序(步骤4), 并使用 “Geneva” Framework 来验证 令牌(Token)并使用其中的声明(Claims)(步骤5)。不需要像如今常见的那样,使用不同的方式处理来至互联网访问的标识(Identity),基于声明的(Claims-Based )方法可以使处理这种情况就像处理企业内部情况一样。

尽管如此,还是有一些额外的复杂性引入进来。例如,当用户在步骤3中请求令牌(Token)时,她如何让STS来验证她自己的? 之前图7中显示的 Kerberos 票据 只能用在当用户在企业内部的时候才能使用,而互联网的用户不能使用。 相对的,用户可能在步骤3中提供 用户名和密码 来验证她的请求(一个可选项 微软 计划 在 “Geneva”服务器中支持这个)。 因为在这个情况中的用户是雇员,他们已经拥有了ADDS 帐号,所以他们可以登录,没有任何问题。

然而如果用户不是雇员呢?假设应用程序需要通过互联网暴露给客户。这个方法还能工作吗?答案毋庸置疑是肯定的。虽然这不是一个特别常见的选择,外部的用户信息和在ADDS中的雇员帐户一起,都可以被“Geneva” 服务器访问。 选择之一是,外部用户帐户和属性(Attribute)信息被保存到 Active Directory 轻型目录服务(Active Directory Lightweight Directory Services,AD LDS) 中。原名是 Active Directory Application Mode (ADAM),这种技术提供简单的目录服务,这也是 “Geneva” 服务器 的可选项之一。

但等一下: 如果互联网用户仍然需要 用户名和密码,基于声明的(Claims-Based )方法 如何使这个做得更好?答案有很多。首先,要认识到用户不再为每个应用程序输入密码。相对的,他们将会(大部分)对于使用的STS只会有一个密码。这就使得应用程序从本来需要保存敏感的密码信息的职责中解脱出来,而这个责任被转移到很少的几个STS上。此外,因为请求令牌(Token)是直接由 CardSpace “Geneva” 发出的——用户永远不会进入这个STS的URL—— 要通过钓鱼攻击(Phishing)获取到这些密码也会变得更加困难。攻击者没有办法将指向自己伪造的STS的URL推送给用户。 虽然 基于声明的标识(Claims-Based Identity)不能消除用户名和密码,但是能改善这种情况。

在图8中显示的,该组织不仅提供了应用程序,也同时担当了标识提供程序(Identity Provider)。 虽然这在很多情况下是合理的,还有一些情况,使用的 标识提供程序(Identity Provider)是外部组织的。例如,如今微软提供的Windows Live ID 就是一个互联网可访问的(Internet-accessible)STS, 还有其他的 标识提供程序(Identity Provider)的存在。虽然可以实现自己的 标识提供程序(Identity Provider)(或者同时使用),但是公司可以创建的应用程序接受来至外部 标识提供程序(Identity Provider)颁发的令牌(Token)。 图9 显示了它的的样子。

clip_image001[22]

Figure 9: An application can accept tokens issued by identity providers run by external organizations.

图9: 应用程序可以接受运行在组织外部的标识提供程序(Identity Provider)所颁发的令牌(Token)

和图8中的示例一样,过程起始于 用户访问应用程序(步骤1),然后选择标识(Identity)(步骤2)。然而,这次,为这个标识(Identity)请求的令牌(Token)是来至运行在外部的标识提供程序(Identity Provider)的STS 提供的(步骤3)。 一旦有了令牌(Token),用户的系统会和往常一样将令牌(Token)提交到应用程序(步骤4),它会使用其中的声明(Claims)(步骤5)。

不要被迷惑:虽然例子中外部的标识提供程序(Identity Provider)之一 是由微软提供的,这绝不是 CardSpace “Geneva” 也不是 基于声明的标识(Claims-Based Identity) 常见的对 提供程序 (Provider)的限制。 任何人都可以实现 STS 来作 标识提供程序(Identity Provider),假设 能使 应用程序信任它们发布的令牌(Token)中的声明(Claims)。

不管是互联网可访问的(Internet-accessible)应用程序信任外部的标识提供程序(Identity Provider)或者 仅仅是自己组织运行的标识提供程序(Identity Provider), 基于声明的(Claims-Based )方法都是很有魅力的。它可以为防火墙内部和外部的用户提供一致的标识(Identity)处理方式。它也可以使应用程序从维护互联网用户使用的用户名/密码的数据库的工作中解脱出来,这使得钓鱼攻击变得无效。同时也使开发者的工作变得简单, 基于声明的标识(Claims-Based Identity) 也可以简化用户的操作。 例如,因为令牌(Token)中包含任何应用程序指定的声明(Claims),用户可以更简单的 通过网站提交常见信息 —— 用户不需要在为每个网站输入了。虽然,数以千计的应用程序开发者和数以百万的用户 的行为 不会一夜改变,但未来是客观的。

 

USING CLAIMS BETWEEN ENTERPRISES 在企业间使用声明(Claim)

 

另一个常见的标识(Identity)挑战是让一个公司中的用户访问运行在另一个公司中的应用程序。例如,假设你的公司希望让在合作伙伴的雇员访问公司内部的SharePoint站点。 有一种办法来是为每个外部的用户分配你的公司的帐号。虽然这个方法可以工作,但却不怎么诱人。这些用户不喜欢使用额外的登录,并且你的公司的管理员也不喜欢去管理公司外部人员的帐号。还有就是这个操作也引来了安全风险——如何知道外部用户什么时候离开了公司,好让你的管理员来关闭这个帐号以不让他使用?

一个更好的解决方案是让外部用户使用它们自己的标识(Identities)访问你的程序。这个方法不需要单独登录和新的帐号。但是却需要在你的公司和合作伙伴之间建立一个联合关系(Federation relationship)。这样做像是在两个公司间指定某种法律协议,不过这个话题超出了本文讨论范围。当然,也需要把这个技术放到合理的位置。

AD FS ,微软的 “Geneva”服务器的前身,允许被动(Passive)客户端(如,浏览器)的联合标识验证(Federation Identity),但是不支持主动(Active)客户端。“Geneva”服务器仍然支持 AD FS 样式的被动选项,通过依赖 WS-Federation 标准。(如果你感兴趣它是如何工作的,可以参考 Digital Identity for .NET Applications: A Technology Overview , 网址:http://msdn.microsoft.com/en-us/library/bb882216.aspx。) 然而,与 CardSpace “Geneva” 和 STS 一起,基于声明的标识(Claims-Based Identity) 也可以用于主动客户端的联合访问(Federated Access)。这使得同样的标识(Identity)技术被使用在其他重要环境中,同时也比使用ADFS,提供了更多的用户控制。

在基于声明的(Claims-Based)世界中,提供联合标识验证(Federation Identity)方法是配置运行在组织的应用程序去信任另一个组织中的STS。 图10 显示它的样子。

clip_image001[24]

图10:如果应用程序信任客户端企业的STS,那么它就能接受和使用那个STS颁发的令牌(Token)。

在这个情况中, 在企业X中的用户访问在企业Y中的应用程序并获取需求信息(步骤1)。在这里,应用程序配置成信任着2个STS,在企业Y中的STS和在企业X中的 STS。 然后需要在企业X中的用户来选择一个满足应用程序需求的标识(Identity)(步骤2),然后从自己的STS那为这个标识(Identity)获取令牌(Token)(步骤3)。浏览器或客户端提交这个令牌(Token)到应用程序(步骤4), 然后使用 “Geneva” Framework 来验证令牌(Token)并提取其中的声明(Claims)。应用程序可以使用任何它喜欢的方式使用这些声明(Claims)(步骤5)。

这个解决方案很简单,但不是没有问题。假设例子中的程序被几个不同企业中的用户使用。使用图10 中的方法,应用程序需要配置信任每一个STS,这将会前景灰暗。更好解决方法是使用联合标识验证(Federation Identity) 的机制通过自己的STS处理。这样做意味着应用程序仅需要信任自己的STS,使构建者和管理的工作变得简单。图11显示了这个更适合的情况的样子。

clip_image001[26]

 

图11:如果应用程序只信任自己的企业的STS,那么客户端必须向那个STS请求令牌(Token)来访问程序。

这个情况中和之前一样的地方开始: 企业X中的用户访问企业Y中的应用程序并获取它的令牌(Token)需求信息(步骤1)。然而,这次应用程序配置成仅信任自己的STS,即 在企业Y中的STS。一旦确认了这个,在用户系统上CardSpace “Geneva” 将会联系在企业Y中的STS来获取它的令牌(Token)需求(步骤2)。同时作为 身份选择器(Identity Selector)角色,CardSpace “Geneva”内置的智能能够穿透这种联合关系(Federation relationship)。然后,CardSpace “Geneva” 提示用户来选择满足这些需求的标识(Identity)(如,通过卡片)(步骤3)并且为这个标识(Identity)从企业X的STS那里请求令牌(Token)(步骤4)。这个令牌(Token)包含了关于这个用户的声明(Claims),但是这个令牌(Token)将不会被应用程序接受——颁布它的STS不是应用程序信任的。相对的,CardSpace “Geneva”提交这个令牌(Token)到在企业Y中的STS(步骤5)。这个STS被配置成信任在企业X中的STS,这种关系必须是通过两个企业的管理员详细的制订出来的。(有关如何创建者这种信任关系的描述的详细信息在后面。) 因为这中信任,在企业Y中的STS可以验证令牌(Token)是来至企业X的,然后发布令牌(Token)来允许用户访问应用程序(步骤6)。用户向应用程序出示这个令牌(Token)(步骤7),并且应用程序使用 “Geneva” Framework 来验证令牌(Token)并提取其中的声明(Claims)。现在应用程序可以使用这些声明(Claims)了(步骤8)。

值得说明的是即使在这两个情景中,“Geneva”服务器出现在STS之中,但它不是必须的。CardSpace “Geneva” 可以和任何供应商的任何STS通讯。还注意到在企业Y中的STS作为声明转换器(Claims Transformer),接受 STS X 颁发的令牌(Token),然后创建自己的令牌(Token)。STS Y创建的令牌(Token)内容可能和从STS X接受过来的令牌(Token)不同——可以随意的添加,删除,或者修改声明(Claims)。

最后,重新思考一下,直接使用令牌(Token)如何方便了应用程序获取需要的有关用户的信息。当用户和应用程序都在用一个组织的时候,应用程序可能访问,如,从AD DS 直接获取信息像是用户的职称。而当他们在不同的组织中的时候,如这里展示的联合示例,应用程序几乎可以肯定的将不会被允许这样做。 把需要的任何东西放到用户的令牌(Token)中是个不错的选择。

 

USING CLAIMS WITH DELEGATION
通过代理使用声明(Claim)

 

这里又有另一个标识(Identity)挑战:假设一个应用程序需要代表某些用户访问另一个应用程序。要解决这个问题需要标识代理(Identity Delegation),应用程序接收用户的标识(Identity)信息并允许作为用户来访问另一个应用程序。虽然代理(Delegation)方式一直以来很重要,甚至对 面向服务(Service-Oriented)的世界带来重大的影响,一个服务依赖另一个服务。再次重申,基于声明的标识(Claims-Based Identity)可以使用在这里。图12显示如何工作的。

clip_image001[28]

图12:基于声明的标识(Claims-Based Identity) 可以与代理一起使用,应用程序代表用户访问另一个应用程序。

这个简单的例子开始于用户的浏览器或者客户端获取应用程序X的令牌(Token)(步骤1)。(虽然没有出现在这里,假设这需求信息的通常步骤显示在先前的图例中。)然后这个令牌(Token)发送给应用程序 X(步骤2)。为了完成用户的请求,应用程序 X 需要调用应用程序Y提供的服务。应用程序 X 可能是一个 Web应用程序,例如,调用应用程序 Y 使用WCF建立的Web服务,或者应用程序 X 自身可能通过 Web 服务被调用。无论哪种情况,应用程序 X 需要用于应用程序 Y 的令牌(Token),它包含描述原始用户的声明(Claims)。 要获取这个令牌(Token),应用程序 X 访问应用程序 Y 并获取它的令牌(Token)需求信息(步骤3)。在这些需求信息中,指出应用程序 Y 可以接受的令牌(Token)的标识提供程序(Identity Provider)(像是STS)。在这个例子中,这个STS和为应用程序 X 颁发令牌(Token)的STS是同一个,虽然不一定非给如此。然而,这里应用程序 X 为应用程序 Y 请求令牌(Token)的STS是它们共用的,并指出应用程序 X 希望代表原始用户(步骤4)。 “Geneva” Server STS 可能包含一个策略 用来描述允许哪个应用程序通过使用代理的方式访问另一个应用程序。STS检查这个策略(步骤5),在这里个例子里允许应用程序 X 代表 用户访问 访问应用程序 Y。然后 STS 发布允许应用程序 X 代表用户访问应用程序 Y 的请求令牌(Token)(步骤6)。 当应用程序 X 调用应用程序 Y 的服务时,应用程序 X 会传递这个令牌(Token)(步骤7)。然后 应用程序 Y 使用 “Geneva” Framework 验证令牌(Token)并使用其中的声明(Claims)(步骤8)。

值得比较的是这个基于声明的(Claims-Based )形式和如今的常见的形式相比更是代理(Delegation)。 一个选择是用户直接传递她的用户名和密码到应用程序 X,然后作为这个用户使用用户名和密码来访问应用程序Y。 然而应用程序X现在已经拥有了用户的登录信息,所以应用程序X可能去做其他用户不允许的事情。如果使用基于声明的(Claims-Based )方法,应用程序X仅拥有这个用户用于访问Y的令牌(Token),没有其他多余信息。另一个方法是提供一个代理(Delegation),一个使应用程序X信任的子系统(Subsystem), 向应用程序提供完整的访问其他服务的能力。 虽然这个可以工作,但是要授予应用程序 X这种宽广的权利需要对于构建和运行它的人有足够信心(译注:前边说的安全问题)。这个方法也使的应用程序Y 不能知道哪些用户正在访问它,因为审计或者其他原因的需求可能需要记录这些信息(译注:哪些用户访问)基于声明的(Claims-Based )代理让应用程序 X 代表个别用户访问 应用程序 Y, 并确保 应用程序Y知道这些用户,不需要扩大信任到整个应用程序 X。

再一次强调,STS 在这里作为一个声明转换器(Claims Transformer)。它接收来至应用程序X的令牌(Token)然后发出给应用程序 Y 的令牌(Token)。这两个令牌(Token)可能包含不同的内容,因为他们是对两个不同的程序颁发的,甚至可能使用了不同的格式。(例如,应用程序 X和 Y可能由不同的人在不同的时间建立的。) 所有这些变化对于应用程序开发者和用户都是通过STS隐藏的。 这也是基于声明的标识(Claims-Based Identity)主要目标之一的另一个例子:使应用程序更简单。