Date de publication initiale de l’article : samedi 02 avril 2011

D’après la ligne d’objet de ce billet, vous aurez sans doute compris que la procédure que nous allons traiter aujourd’hui promet d’être très intéressante.  Ce billet traite d’un problème qui me tracasse (moi et de nombreuses autres personnes) depuis bien longtemps.  J’ai récemment commencé à en parler autour de moi et je viens de recevoir un message électronique de quelqu’un qui venait justement d’obtenir des informations sur la manière de résoudre ce problème.

 

Je vais couvrir uniquement les aspects les plus courants de ce scénario ; il existe de nombreuses variantes qui peuvent venir s’y greffer.   Le problème concerne l’extraction de données à partir d’un site SharePoint qui utilise plusieurs fournisseurs d’authentification ; dans ce scénario, supposez que l’un des fournisseurs concerne les revendications Windows et que l’autre concerne tout autre système d’authentification (basée sur les formulaires ou sur SAML, par exemple).  Il peut arriver fréquemment que vous souhaitiez extraire des données d’un tel site à l’aide du modèle objet client ou des services Web SharePoint, mais que vous utilisiez pour cela l’authentification Windows.  À ce stade, le problème a toujours été que même lorsque vous définissez vos informations d’identification Windows sur la demande, vous recevez un message Accès refusé lorsque vous demandez les données.

 

La résolution sous-jacente à ce problème est que si vous souhaitez accéder par programme à un site SharePoint qui utilise plusieurs fournisseurs d’authentification avec un jeu d’informations d’identification Windows, vous devez ajouter un en-tête supplémentaire à votre demande.  Le nom de l’en-tête doit être X-FORMS_BASED_AUTH_ACCEPTED et la valeur doit être « f ».  L’ajout de cet en-tête peut être un peu compliqué pour ces deux scénarios courants ; dans le reste de ce billet, je vais donc expliquer comment procéder à l’aide d’un exemple de code.

 

Si vous utilisez le modèle objet client, vous devez ajouter un gestionnaire d’événement pour l’événement ExecutingWebRequest.  Voici un exemple du code à implémenter :

 

//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

}

 

And this is where the magic happens:

 

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);

       }

}

 

Voilà. Je pense que ce code ne pose aucune difficulté et se passe d’explications.  Effectuer la même opération avec une référence de service Web standard est quelque peu différent.  Pour commencer, ajoutons une référence Web de style standard dans un site SharePoint à un projet dans Visual Studio 2010 :

1.       Cliquez avec le bouton droit sur le nœud Référence de service et sélectionnez Ajouter une référence de service.

2.       Cliquez sur le bouton Avancé au bas de la boîte de dialogue.

3.       Cliquez sur le bouton Ajouter une référence Web au bas de la boîte de dialogue suivante.

4.       Entrez l’URL du service Web que vous souhaitez utiliser dans la zone d’édition URL ; par exemple, pour ajouter une référence au service Web Listes dans le site à l’adresse http://foo, vous devez insérer ce qui suit comme URL :  https://foo/_vti_bin/lists.asmx.

5.       Appuyez sur la touche Entrée ou cliquez sur la flèche verte pour rechercher la référence de service Web, puis tapez un nom pour votre référence de service Web dans la zone d’édition Nom de la référence Web et cliquez sur le bouton Ajouter une référence.

 

Votre référence et ses classes proxy devraient maintenant être créées, mais vous devrez ajouter une classe partielle supplémentaire afin d’ajouter l’en-tête à votre demande de service Web.  Commencez par ajouter une nouvelle classe à votre projet et affectez-lui le nom de votre choix.  Étant donné que vous souhaitez simplement ajouter un comportement supplémentaire (ajouter un en-tête à la demande), la classe que vous ajoutez doit être partielle.  Cela signifie que vous devez copier à la fois l’espace de noms et le nom de la classe utilisés dans le proxy créé pour votre référence Web. Voici comment procéder :

 

1.       Cliquez sur le bouton Afficher tous les fichiers dans la fenêtre Explorateur de solutions de Visual Studio.

2.       Cliquez sur le signe plus en regard de votre référence de service Web afin de la développer.

3.       Cliquez sur le signe plus en regard du fichier Reference.map afin de le développer.

4.       Double-cliquez sur le fichier Reference.cs pour l’ouvrir.

5.       Copiez l’espace de noms et collez-le dans votre classe.

6.       Copiez le nom de la classe, y compris l’héritage, et collez-le dans votre classe comme nom de la classe.  La classe de référence de service Web étant une classe partielle, vous n’avez aucune modification à apporter ici.

 

Voici un exemple de ce à quoi ressemblait la classe Reference.cs pour ma référence de service Web :

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 {

 

Et voici ce que j’ai collé dans la classe que j’ai créée :

namespace ClientOmAuth.listsWS

{

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

       {

       }

}

 

Vous remarquerez que l’espace de noms et les noms des classes correspondent tous deux et que les deux classes héritent du même type de base.

 

Vous devez maintenant substituer la méthode GetWebRequest afin de pouvoir ajouter l’en-tête.   Pour cela, il vous suffit d’ajouter le code suivant à votre classe partielle :

 

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;

}

 

 

Le codage permettant d’extraire les données via le service Web est maintenant rigoureusement identique à celui que l’on utiliserait avec tout site SharePoint à authentification Windows :

 

//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

}

 

Et voilà ; nous avons terminé.  Vous pouvez également appliquer ces informations à l’extraction de données via REST, à l’aide des techniques décrites dans le billet ci-dessous :  http://blogs.technet.com/b/speschka/archive/2010/09/25/retrieving-rest-data-in-a-claims-based-auth-site-in-sharepoint-2010.aspx.

 

Ce billet de blog a été traduit de l’anglais. L’article d’origine se trouve à l’adresse Retrieving Data from a Multi Auth Site Using the Client OM and Web Services in SharePoint 2010