최초 문서 게시일: 2011년 4월 2일 토요일

이 게시물의 내용은 제목만으로도 충분히 짐작이 되시리라 생각합니다. 여기서는 저는 물론 다른 개발자들을 오랫동안 괴롭혀 왔던 문제를 해결하는 방법을 알려 드리겠습니다. 최근에 이 문제에 대해 많은 사람들에게 질문을 한 결과, 이 문제를 해결하는 방법에 대한 정보를 얻은 분으로부터 전자 메일을 받을 수 있었습니다.

 

이 게시물에서는 이러한 시나리오의 가장 일반적인 부분에 대해서만 다루며, 다양하게 변형된 사례가 있을 수 있습니다. 여기서 설명할 기본적인 문제는, 다중 인증 공급자를 사용하는 SharePoint 사이트에서 데이터를 검색하는 것입니다. 인증 방법 중 하나는 Windows 클레임이고, 다른 하나는 양식 기반 인증, SAML 인증 등 다른 방법이라고 가정하겠습니다. 클라이언트 OM 또는 SharePoint 웹 서비스를 사용하여 이러한 사이트에서 데이터를 검색하는 경우가 많은데, 이때 일반적으로는 Windows 인증을 사용하게 됩니다. 이 경우 요청에 대해 Windows 자격 증명을 설정해도 데이터 요청 시 액세스 거부 오류가 발생하게 됩니다.

 

이 문제를 근본적으로 해결하려면, Windows 자격 증명 집합이 포함된 여러 인증 공급자를 사용하는 SharePoint 사이트에 프로그래밍 방식으로 액세스하려는 경우 요청에 헤더를 더 추가해야 합니다. 헤더 이름은 X-FORMS_BASED_AUTH_ACCEPTED여야 하고 값은 "f"여야 합니다. 이 헤더를 추가하는 것은 이러한 두 일반적인 시나리오에 비해 약간 복잡할 수 있으므로, 이 게시물의 뒷부분에서는 예제 코드를 통해 헤더를 추가하는 방법을 설명합니다.

 

클라이언트 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);

       }

}

 

이 코드는 매우 간단해서 추가 설명은 필요하지 않을 것 같네요. 그러나 표준 웹 서비스 참조를 사용하는 경우에는 같은 작업이라도 방법이 약간 달라집니다. 먼저 SharePoint 사이트에서 표준 스타일 웹 참조를 Visual Studio 2010의 프로젝트에 추가하는 과정을 단계별로 살펴보겠습니다.

1.       서비스 참조 노드를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 선택합니다.

2.       대화 상자 아래쪽의 고급 단추를 클릭합니다.

3.       다음 대화 상자 아래쪽의 웹 참조 추가… 단추를 클릭합니다.

4.       URL 편집 상자에 사용할 웹 서비스의 URL을 입력합니다. 예를 들어 http://foo 사이트의 목록 웹 서비스에 대한 참조를 추가하려면 URL로 https://foo/_vti_bin/lists.asmx를 입력합니다.

5.       Enter 키를 누르거나 녹색 화살표 단추를 클릭하여 웹 서비스 참조를 찾은 다음, 웹 참조 이름 편집 상자에 웹 서비스 참조의 이름을 입력하고 참조 추가 단추를 클릭합니다.

 

참조 및 참조의 프록시 클래스가 만들어졌습니다. 웹 서비스 요청에 헤더를 추가하려면 부분 클래스를 더 추가해야 합니다. 먼저 프로젝트에 새 클래스를 추가하고 원하는 이름을 지정합니다. 일부 동작만 추가할 것이므로(요청에 헤더 추가), 헤더를 부분 클래스로 만듭니다. 즉, 웹 참조용으로 만든 프록시에 사용되는 클래스 이름과 네임스페이스를 모두 복사해야 합니다. 다음은 이 작업을 수행하는 단계입니다.

 

1.       Visual Studio의 솔루션 탐색기 창에서 모든 파일 표시 단추를 클릭합니다.

2.       웹 서비스 참조 옆의 더하기 기호를 클릭하여 참조를 확장합니다.

3.       Reference.map 파일 옆의 더하기 기호를 클릭하여 파일을 확장합니다.

4.       Reference.cs 파일을 두 번 클릭하여 엽니다.

5.       네임스페이스를 복사하여 클래스에 붙여 넣습니다.

6.       상속을 포함하여 클래스 이름을 복사한 다음 클래스에 클래스 이름으로 붙여 넣습니다. 웹 서비스 참조 클래스는 이미 부분 클래스이므로 변경할 필요가 없습니다.

 

제가 웹 서비스 참조용으로 작성한 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="http://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;

}

 

 

이제 웹 서비스를 통해 데이터를 검색하는 코드는 일반 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

}

 

보시다시피 코드는 매우 간단합니다. 이 정보는 http://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을 참조하십시오.