다음을 통해 공유


在 SharePoint 2010 中使用 Client OM 和 Web 服务从多身份验证网站检索数据

原文发布于 2011 年 4 月 2 日(星期六)

从本文的标题来看,如果今天什么都要说的话,那内容可就多了。 本文主要解决长期以来一直困扰我和其他人的问题。 我最近才开始问及该问题,然后偶然收到来自某人的一封电子邮件,说他刚知道如何解决该问题。

 

我只讲述该应用场景最常见的部分;因为它可能变得非常复杂。 问题是从使用多个身份验证提供程序的 SharePoint 网站检索数据;在该应用场景中,假设一个是 Windows 声明,而另一个则是其他什么东西(可以是基于表单的身份验证或是 SAML 身份验证)。 通常,您需要使用 Client OM 或 SharePoint Web 服务而不是 Windows 身份验证来从此类网站检索数据。 到此问题就出来了,即使您对请求设置了 Windows 凭据,还是会在请求数据时被“拒绝访问”。

 

对于该问题的基本解决方案是,如果您想要使用一组 Windows 凭据以编程方式访问使用多个身份验证提供程序的 SharePoint 网站,那么您需要对请求添加一个额外的标头。 标头名称需要为 X-FORMS_BASED_AUTH_ACCEPTED 而且值需要为“f”。 添加此标头对于这两个常见的应用场景来说,可能稍显复杂,所以本文的余下部分将介绍如何使用一些示例代码来解决问题。

 

如果您使用的是 Client OM,则需要添加 ExecutingWebRequest 事件的事件处理程序。 下面是该代码的示例及其用法:

 

//create the client context

ClientContext ctx = new ClientContext(MixedUrlTxt.Text);

//configure the handler that will add the header

ctx.ExecutingWebRequest +=

new EventHandler<WebRequestEventArgs>(ctx_MixedAuthRequest);

//set windows creds

ctx.AuthenticationMode = ClientAuthenticationMode.Default;

ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;

//get the web

Web w = ctx.Web;

//LOAD LISTS WITH ALL PROPERTIES

var lists = ctx.LoadQuery(w.Lists);

//execute the query

ctx.ExecuteQuery();

//enumerate the results

foreach (List theList in lists)

{

//do something with each list

}

 

这就是见证奇迹的地方:

 

void ctx_MixedAuthRequest(object sender, WebRequestEventArgs e)

{

try

{

              //add the header that tells SharePoint to use Windows Auth

              e.WebRequestExecutor.RequestHeaders.Add(

"X-FORMS_BASED_AUTH_ACCEPTED", "f");

       }

       catch (Exception ex)

       {

              MessageBox.Show("Error setting auth header: " + ex.Message);

       }

}

 

就这么多了,该代码非常简单,我相信可以无师自通。 对标准的 Web 服务引用执行相同的操作时则有点不同。 开始前,让我们先了解一下将 SharePoint 网站中标准样式的 Web 引用添加至 Visual Studio 2010 中项目的流程:

1. 右键单击“服务引用”节点并选择“添加服务引用”。

2. 单击对话框底部的“高级”按钮。

3. 单击下一个对话框底部的“添加 Web 引用…”按钮。

4. 在 URL 编辑框中输入指向要使用的 Web 服务的 Url;例如,若要在网站 https://foo 中添加对列表 Web 服务的引用,我会输入以下 URL: https://foo/_vti_bin/lists.asmx。

5. 按 Enter 或单击绿色箭头按钮以找到 Web 服务引用,然后在 Web 引用名称编辑框中键入 Web 服务引用的名称并单击“添加引用”按钮。

 

此时应该创建您的引用和引用的代理类,但是您将需要添加一个额外的分部类以便将标头添加至您的 Web 服务请求。 先向您的项目添加一个新类,然后给它取一个您喜欢的名字。 由于您只是想增加一些额外的行为(将标头添加至请求),因此您将需要使用分部类。 这意味着您需要同时复制为 Web 引用创建的代理中使用的命名空间和类名。下面是执行该操作的步骤:

 

1. 单击 Visual Studio 的“解决方案资源浏览器”窗口中的“显示所有文件”按钮。

2. 单击 Web 服务引用旁边的加号以将其展开。

3. 单击 Reference.map 文件旁边的加号以将其展开。

4. 双击 Reference.cs 文件以将其打开。

5. 复制命名空间并将其粘贴到您的类中。

6. 复制类名,包括继承,并将其作为类名粘贴到您的类中。 Web 服务引用类已是分部类,所以不需要对它做什么更改。

 

下面的示例中,您可以看到我的 Web 服务引用的 Reference.cs 类是怎样的:

namespace ClientOmAuth.listsWS {

    using System;

    using System.Web.Services;

    using System.Diagnostics;

    using System.Web.Services.Protocols;

    using System.ComponentModel;

    using System.Xml.Serialization;

   

   

    /// <remarks/>

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Web.Services.WebServiceBindingAttribute(Name="ListsSoap", Namespace="https://schemas.microsoft.com/sharepoint/soap/")]

    public partial class Lists : System.Web.Services.Protocols.SoapHttpClientProtocol {

这就是我向创建的类中粘贴的内容:

namespace ClientOmAuth.listsWS

{

       public partial class Lists : System.Web.Services.Protocols.SoapHttpClientProtocol

       {

       }

}

所以您将注意到命名空间类名是如何匹配的,并且该两个类都是继承自同一个基本类型。

 

现在您需要替代 GetWebRequest 方法,以便可以添加标头。 为此,只需将此代码添加到您的分部类中:

protected override System.Net.WebRequest GetWebRequest(Uri uri)

{

       System.Net.WebRequest wr = null;

       try

       {

              wr = base.GetWebRequest(uri);

              wr.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");

       }

       catch (Exception ex)

       {

              //some error handling here

       }

                          

       return wr;

}

 

针对通过 Web 服务检索数据进行编码现在与您对任何 Windows 身份验证 SharePoint 网站所做的完全相同:

 

//create the web service proxy and configure it use my Windows credentials

listsWS.Lists lws = new listsWS.Lists();

lws.UseDefaultCredentials = true;

//get the collection of lists

XmlNode xLists = lws.GetListCollection();

//enumerate results

foreach (XmlNode xList in xLists.ChildNodes)

{

//do something with each List

}

就这么多了。 您也可以应用此信息通过 REST 检索数据,使用我下面介绍的技术即可: https://blogs.technet.com/b/speschka/archive/2010/09/25/retrieving-rest-data-in-a-claims-based-auth-site-in-sharepoint-2010.aspx(该链接可能指向英文页面)

 

这是一篇本地化的博客文章。请访问 Retrieving Data from a Multi Auth Site Using the Client OM and Web Services in SharePoint 2010 以查看原文