Partager via


声明、Azure 和 SharePoint 集成工具包(第 2 部分)

声明、Azure 和 SharePoint 集成工具包(第 2 部分)

这是 CASI(声明、Azure 和 SharePoint 集成)工具包系列文章的第 2 部分,本系列共 5 部分。 第 1 部分概括性介绍整个框架和解决方案并说明本系列文章要尝试解决的问题及涵盖的内容。 在本博客中,我们将重点介绍方法模式:

1. 使用自定义 WCF 应用程序作为数据和内容的前端

2. 使 WCF 应用程序能够识别声明

3. 进行其他一些更改,以便能够将 WCF 应用程序提升到 Windows Azure 云

使用 WCF

CASI 工具包框架的主要前提是所有应用程序数据都使用 WCF 应用程序作为前端。 与所有自定义应用程序一样,这是开发人员需要创建的内容。 项目的这一部分内容实际上不需要具有专门的 SharePoint 知识,可以使用 Visual Studio 创建 WCF 应用程序的任何 .NET 开发人员都可以完成此操作。 如果您的最终目标是在 Windows Azure 中承载此 WCF 服务,强烈建议您使用 Windows Azure 开发工具包下载用于创建 Azure 应用程序的模板,从一开始就创建 Azure WCF 应用程序。 您要了解 CASI 工具包当前版本的一个重要限制,因此需要在此处指出这项限制。 CASI 工具包实际上仅支持将核心 .NET 数据类型作为参数发送到 WCF 方法。 因此,字符串、布尔值、整数和日期可以正常工作,但是没有将自定义类作为参数传递的方法。 然而,如果需要这样做,则建议您创建字符串形式的参数,在调用 WCF 方法之前将参数反序列化为 Xml,然后在 WCF 代码中将它重新序列化为对象实例。 除此之外,到目前为止我还没有发现任何重要限制,但是我相信在这项技术得到越来越广泛的采纳和使用后,您的愿望将很快得以实现。 补充说明一点,您现在看到的工具包实际上只是我自己设计的 1.0 版,用于解决如何才能将所有这些内容联系在一起并符合我认为重要的核心情况。 随着人们对这项技术的采用,我相信有很大的改进空间。

使 WCF 应用程序能够识别声明

创建 WCF 应用程序后,下一步是使它能够识别声明。 对于此步骤,我绝对不敢居功。我只是指出这种方法,并向您推介由 Office 团队的 Eric White 编写的出色的博客文章(共 4 部分),以便介绍如何将 SharePoint 声明集成到 WCF 应用程序中。 假定您已经构建了 WCF 服务,因此我将从 Eric 博客系列文章的第 2 部分开始,文章网址为: https://blogs.msdn.com/b/ericwhite/archive/2010/05/13/determining-caller-identity-within-a-wcf-web-service.aspx(该链接可能指向英文页面)。 此外,您必须继续执行他在第 3 部分概述的步骤,文章网址为: https://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx(该链接可能指向英文页面) (从具有以下标题的部分开始: 过程:在 Web 服务和 SharePoint Server 之间建立信任关系。 您需要执行从此处开始的所有步骤,执行这些步骤实际上是复制 SharePoint STS 令牌签名证书的指纹,并将它和一些其他信息复制到 WCF 应用程序的 web.config 文件中。 我没有逐步执行第 3 部分中的 SSL 步骤,因为在 Windows Azure 中承载应用程序时使用自签名证书实际上没有什么意义。 如果您没有其他规划,则您只需完成这些步骤即可,但您通常应该规划如何从适当的证书颁发机构为您的 Windows Azure WCF 应用程序获取适当的 SSL 证书。 注意:需要执行 Eric 博客的第 4 部分中的步骤。 现在,只要执行上述步骤,您即会具有一个能够识别 SharePoint 声明的有效 WCF 应用程序。 在本博客的最后,我将指导您完成其他一些必需步骤,以便将该 WCF 应用程序提升到 Windows Azure。

使 WCF 应用程序能够在 Windows Azure 中工作

现在,您具有了有效的 WCF Azure 应用程序,您需要执行一些其他操作,以使该应用程序继续通过 Windows Identity Framework (WIF) 支持声明身份验证和令牌并在 Windows Azure 云中承载该应用程序。 此处只提供简单的列表:

1. 将 WebRole 项目(即 WCF 项目)配置为使用本地虚拟目录进行调试。 对于使用证书(您正要这样做)的项目,我发现进行此配置比配置 VS.NET 开发服务器容易得多。 若要进行此更改,请双击 WebRole 项目属性,然后单击“Web”选项卡。 选择“使用本地 IIS Web 服务器”单选按钮,然后单击“创建虚拟目录”按钮。 创建虚拟目录后,可以关闭项目属性。

2. 在 WebRole 项目中添加对 Microsoft.Identity 的引用。 您必须对引用进行如下更改:Copy Local = trueSpecific Version = false。 使用应用程序包将 WIF 程序集复制到云时需要这样做。

3. 获取以下 WCF 修补程序: https://code.msdn.microsoft.com/KB981002/Release/ProjectReleases.aspx?ReleaseId=4009(该链接可能指向英文页面) 适用于 Win2k8 R2; https://code.msdn.microsoft.com/KB971842/Release/ProjectReleases.aspx?ReleaseId=3228(该链接可能指向英文页面) 适用于 Win2k8。

4. 您必须将以下属性添加到 WCF 类中: [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]. 因此,该类应该如下所示:

namespace CustomersWCF_WebRole

{

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

    public class Customers : ICustomers

    {

5. 您必须在服务使用的行为元素中包含以下配置数据。 它解决在 Azure 环境中进行随机端口分配时可能出现的问题。 若要在本地对其进行测试,您需要获取上文第 3 步中所介绍的修补程序:

      <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

下面是我的 WCF 服务的 web.config 上下文中的示例:

    <behaviors>

      <serviceBehaviors>

        <behavior name="CustomersWCF_WebRole.CustomersBehavior">

          <federatedServiceHostConfiguration name="CustomersWCF_WebRole.Customers"/>

          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>

          <serviceDebug includeExceptionDetailInFaults="false"/>

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

        </behavior>

      </serviceBehaviors>

    </behaviors>

6. 首先将要用于 WCF 应用程序的 SSL 证书上载到 Azure 开发人员门户。 注意: CASI 工具包基类硬编码为使用 SSL,因此在 WCF Windows Azure 应用程序中必须实现 SSL 支持。 希望这应该是在云服务和 SharePoint 场之间传递潜在敏感数据的预期要求。然后,在 Visual Studio 中通过双击 WebRole 项目名称(在“角色”文件夹中)将证书添加到 Azure 角色属性。 我发现使用通配符证书行得通。 您需要 PFX 证书,并确保在创建 PFX 文件时导出链中的所有证书。 将该证书上载到开发人员门户时 Azure 将对它们进行扩展。

7. 尽管所有 Azure 应用程序都在 cloudapp.net 上承载,但是您的 SSL 证书应该用于 someName.yourDnsName.com。 例如,我的 SSL 证书是用于 *.vbtoys.com 的通配符证书。 在 DNS 中,我创建了一个称为 azurewcf.vbtoys.com 的新 CNAME 记录,并且它引用 myAzureApp.cloudapp.net。 因此,在连接到 https://azurewcf.vbtoys.com 时,我的证书有效,因为我的请求和 SSL 证书用于 *.vbtoys.com,但 DNS 会根据 CNAME 记录(即 myAzureApp.cloudapp.net)重定向我的请求。

8. 在 Azure 项目中,双击 WebRole 项目名称(在“角色”文件夹)中,并按照如下方式设置这些属性:

a. “配置”选项卡: 取消选中以下项的启动浏览器: HTTP 和 HTTPS 终结点

b. “证书”选项卡: 添加要用于服务的 SSL 证书。 例如,在我的实验室中,我使用由我的域为我的所有 Web 服务器颁发的通配符证书,因此在这里我添加了我的通配符证书。

c. “终结点”选项卡: 选中 HTTP 和 HTTPS 对应的框(名称应该分别为 HttpIn 和 HttpsIn)。 在 HTTPS 部分,SSL 证书名称下拉列表现在应该包含您在步骤 b 中添加的 SSL 证书。

9. 如果您的 WCF 方法返回脚本,则脚本标记必须包含 DEFER 属性,以使其能够在使用随 CASI 工具包提供的 Web 部件时正常工作;您自己的 JavaScript 函数将它分配给标记的 innerHTML 时也应该如此。 例如,您的脚本标记应如下所示:<script defer language='javascript'>

10. 如果您的 WCF 方法返回的内容包含其他格式标记(如 <style>),则需要将这些格式标记包装在 <pre> 标记中,否则在使用随 CASI 工具包提供的 Web 部件时将不会正确处理它们;您自己的 JavaScript 函数将它分配给标记的 innerHTML 时也应该如此。 例如,带样式标记的返回内容应如下所示:<pre><style>.foo {font-size:8pt;}</style></pre>

这些是配置 WCF 应用程序以在 Azure 中承载时需要执行的步骤;下面提供了其他一些有用或在某些情况下必须执行的提示,具体取决于您的实现情况:

1. 创建使用服务的终结点地址时使用完全限定名称,例如 machineName.foo.com 而不是仅 machineName。 这样会更清楚地转换为在 Windows Azure 上承载的最终格式,并且还可以消除 SSL 证书使用完全限定的域名时出现的错误。

2. 如果要通过 SSL 获取 WSDL,您可能 要向以下元素中添加属性 httpsGetEnabled="true":<serviceMetadata httpGetEnabled="true" />。 但是 SharePoint Designer 中当前存在阻止您对 WSDL 使用 SSL 的错误。

3. 有关调试和数据连接提示,请参阅我的博客: https://blogs.technet.com/b/speschka/archive/2010/09/19/azure-development-tips-for-debugging-and-connection-strings.aspx(该链接可能指向英文页面)

4. 在大多数情况下,您应该假定 WCF 服务命名空间为 https://tempuri.org。 有关如何对其进行更改的说明,可以参阅以下博客: https://blogs.infosupport.com/blogs/edwinw/archive/2008/07/20/WCF_3A00_-namespaces-in-WSDL.aspx(该链接可能指向英文页面)

完成的 WCF 服务

如果您已执行所有上述配置步骤并且已将 WCF 应用程序部署到 Windows Azure,则用户从 SharePoint 网站调用该 WCF 服务时,您还将获得该用户的整个用户令牌以及与令牌相关联的所有声明。 另外需要说明的是,进行这些更改后,WCF 服务还将在内部部署中运行,因此如果要在将应用程序推送到云之前尝试进行额外更改,可以很轻松地进行测试。 具有该用户令牌后,您即可在 WCF 服务中执行一些所需操作。 例如,在 WCF 服务中,您可以枚举所有用户的声明并在此基础上做出任何类型的细化权限决策。 下面的示例说明如何对一组用户声明使用 LINQ 以确定当前用户是否是管理员,因为如果该用户是管理员,则在请求中将返回其他一些级别的详细信息:

//look for the claims identity

IClaimsIdentity ci =

System.Threading.Thread.CurrentPrincipal.Identity as IClaimsIdentity;

if (ci != null)

{

//see if there are claims present before running through this

       if (ci.Claims.Count > 0)

       {

       //look for a group claim of domain admin

var eClaim = from Microsoft.IdentityModel.Claims.Claim c in ci.Claims

              where c.ClaimType ==

"https://schemas.microsoft.com/ws/2008/06/identity/claims/role" &&

                     c.Value == "Domain Admins"

                     select c;

              //see if we got a match

              if (eClaim.Count() > 0)

              //there’s a match so this user has the Domain Admins claim

                     //do something here

}

}

同样很酷的功能是您还可以直接对 WCF 方法设置权限要求。 例如,假定您具有一个查询数据存储并返回客户 CEO 列表的 WCF 方法。 您不希望此信息供所有员工使用,只希望供销售经理使用。 一种非常灵活且简单的实现方式是对方法设置 PrincipalPermission 要求,如下所示:

//the customer CEO list should not be shared with everyone,

//so only show it to people in the Sales Manager role

[PrincipalPermission(SecurityAction.Demand, Role = "Sales Managers")]

public string GetCustomerCEOs()

{

//your code goes here

}

现在,如果有人尝试调用此方法,并且如果他们不具有“销售经理”的声明,则他们运行尝试调用此方法的代码时,会拒绝他们访问。 非常酷!

了解不能对此方法进行非授权访问也非常重要。 例如,您不能只在实验室中创建自己的域,在域中添加帐户,并创建销售经理角色(您将在其中添加该帐户)。 不能这样做的原因要追溯到按照 Eric White 的博客执行的步骤(上文中标题为“使 WCF 应用程序能够识别声明”的部分)。 如果您回忆一下,会想起添加了 SharePoint STS 使用的令牌签名证书的指纹。 这意味着声明进入 WCF 应用程序时,它会查找由 SharePoint STS 的公钥签名的令牌。 只有 SharePoint STS 可以使用该公钥对它进行签名,因为它是具有该令牌签名证书的私钥的唯一实体。 这样可以确保您(唯一向该 SharePoint 场进行身份验证的用户)能够使用 WCF 服务,并且用户只具有登录时授予他们的声明。 关于用户声明,非常重要的另外一点是它不仅包含用户向用户目录进行身份验证时授予他们的声明,还包括在 SharePoint 中使用任何自定义声明提供程序通过声明扩充提供给他们的其他任何 ALSO 声明。 因此,这是真正集成的端到端解决方案。

后续步骤

在下一篇博客中,我将开始介绍随 CASI 工具包提供的自定义基类和 Web 部件,您可以通过它们快速而轻松地连接到新 Azure WCF 应用程序。 另外,我将在此基础上利用我为 CASI 工具包编写的 WCF 服务来演示该功能。 在此博客中,我附加了用于此服务的 .cs 文件。 您不能按原样使用该文件,提供它只是方便您了解其中所包含的不同方法和数据类型以及如何为此工具包实现特定功能。 在后面的博客中您将主要了解如何使用 a) GetAllCustomersHtml、b) GetCustomerCEOs 和 c) GetAllCustomers 方法。 它们非常重要,因为它们 a) 返回 HTML(它实际上是在 Web 部件中显示数据的首选返回类型),b) 使用 PrincipalPermission 要求 c) 演示如何从 WCF 应用程序返回自定义类类型,以及通过 CASI 工具包在 SharePoint 中获取同一富类类型后如何使用该数据。

这是一篇本地化的博客文章。请访问 The Claims, Azure and SharePoint Integration Toolkit Part 2 以查看原文。