SharePoint 2010 でクライアント オブジェクト モデルと Web サービスを使用してマルチ認証サイトからデータを取得する
原文の記事の投稿日: 2011 年 4 月 2 日 (土曜日)
私たちが現在扱っていることを表すとするなら、この投稿のタイトル 1 行では言い尽くせません。 この投稿では、私たちユーザーを長く悩ませている問題に対応します。 この問題について周囲に質問し始めたのはごく最近のことです。偶然にも、この問題の解決方法についての情報を得た人から電子メールを受け取りました。
ここでは、このシナリオの最も一般的な部分についてのみ説明します。この部分に足すことのできる工夫はいくつもあります。 問題は、複数の認証プロバイダーを使用している SharePoint サイトからのデータの取得です。このシナリオでは、1 つは Windows クレームで、もう 1 つは何か別のものであるとします。フォーム ベース認証でも SAML 認証でも構いません。 クライアント オブジェクト モデルまたは SharePoint Web サービスのどちらかを使用してこのようなサイトからデータを取得することはよくありますが、そのためには Windows 認証が必要です。 これまでの問題は、常に、要求に基づき Windows 資格情報を設定してもデータの要求時にアクセス拒否が発生することでした。
この問題の基本的な解決策は、一連の Windows 資格情報で、複数の認証プロバイダーを使用する SharePoint サイトにプログラムによってアクセスする場合は、要求にさらにヘッダーを追加する必要がある、ということです。 ヘッダー名は X-FORMS_BASED_AUTH_ACCEPTED に設定し、値は “f” に設定する必要があります。 このヘッダーの追加は、これらの 2 つの一般的なシナリオではあまり簡単ではない可能性があるので、この投稿の残りの部分では、サンプル コードでこの設定を行う方法を説明します。
クライアント オブジェクト モデルを使用している場合は、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. [サービス参照] (Service Reference) ノードを右クリックし、[サービス参照の追加] (Add Service Reference) を選択します。
2. ダイアログ ボックスの下部にある [詳細設定] (Advanced) ボタンをクリックします。
3. 次のダイアログ ボックスの下部にある [Web 参照の追加…] (Add Web Reference…) ボタンをクリックします。
4. [URL] 編集ボックスに、使用する Web サービスの URL を入力します。たとえば、サイト https://foo にあるリスト Web サービスへの参照を追加するには、[URL] に "https://foo/_vti_bin/lists.asmx" と入力します。
5. Enter キーを押すか、緑色の矢印ボタンをクリックして、Web サービス参照を検出します。次に、[Web 参照名] (Web reference name) 編集ボックスに Web サービス参照の名前を入力し、[参照の追加] (Add Reference) ボタンをクリックします。
参照と、その参照のプロキシ クラスを作成する必要がありますが、ヘッダーを Web サービス要求に追加するためにはさらに部分クラスを追加する必要があります。 まず、新しいクラスをプロジェクトに追加し、必要に応じてそのクラスを呼び出します。 ヘッダーを要求に追加して、何らかの動作をさらに追加できるので、それを部分クラスにします。 つまり、Web 参照用に作成したプロキシで使用する名前空間とクラス名の両方をコピーする必要があります。 以下に、その手順を示します。
1. Visual Studio の [ソリューション エクスプローラー] (Solution Explorer) ウィンドウで [すべてのファイルの表示] (Show All Files) ボタンをクリックします。
2. Web サービス参照の横の正符号をクリックして、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
}
これだけのことです。 この情報は、私の別のブログ ( https://blogs.technet.com/b/speschka/archive/2010/09/25/retrieving-rest-data-in-a-claims-based-auth-site-in-sharepoint-2010.aspx (英語)) で説明した方法を使用して、REST を介してデータを取得する場合にも当てはまります。
これはローカライズされたブログ投稿です。原文の記事は、「Retrieving Data from a Multi Auth Site Using the Client OM and Web Services in SharePoint 2010」をご覧ください。