web-dev-qa-db-fra.com

La requête HTTP n'est pas autorisée avec le schéma d'authentification client 'Ntlm'. L'en-tête d'authentification reçu du serveur était 'NTLM'.

Je sais qu'il y a beaucoup de questions SO semblables à celles-ci, mais je n'ai pas pu en trouver une pour cette question particulière.

Quelques points, d’abord:

  • J'ai aucun contrôle sur notre serveur Sharepoint. Je ne peux pas modifier aucun IIS paramètres.
  • Je crois que notre IIS version du serveur est IIS 7.0.
  • Notre serveur Sharepoint anticipe les demandes via NTLM.
  • Notre serveur Sharepoint se trouve sur le même domaine que mon ordinateur client.
  • J'utilise .NET Framework 3.5, Visual Studio 2008

J'essaie d'écrire une application console simple pour manipuler les données Sharepoint à l'aide des services Web Sharepoint. J'ai ajouté la référence de service et voici mon app.config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="ListsSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://subdomain.companysite.com/subsite/_vti_bin/Lists.asmx"
            binding="basicHttpBinding" bindingConfiguration="ListsSoap"
            contract="ServiceReference1.ListsSoap" name="ListsSoap" />
    </client>
</system.serviceModel>

Ceci est mon code:

static void Main(string[] args)
{
    using (var client = new ListsSoapClient())
    {
        client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("username", "password", "domain");
        client.GetListCollection();
    }
}

Lorsque j'appelle GetListCollection (), le message MessageSecurityException est renvoyé:

The HTTP request is unauthorized with client authentication scheme 'Ntlm'.
The authentication header received from the server was 'NTLM'.

Avec une exception WebException:

"The remote server returned an error: (401) Unauthorized."

J'ai essayé diverses liaisons et divers ajustements de code pour essayer de m'authentifier correctement, mais en vain. Je vais énumérer ceux ci-dessous.


J'ai essayé les étapes suivantes:

Utilisation d'un imitateur Win32 natif avant de créer le client

using (new Impersonator.Impersonator("username", "password", "domain"))
using (var client = new ListsSoapClient())
{
    client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("dpincas", "password", "domain");
    client.GetListCollection();
}

Cela a produit le même message d'erreur.


Définition de TokenImpersonationLevel pour les informations d'identification de mon client

using (var client = new ListsSoapClient())
{
    client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
    client.GetListCollection();
}

Cela a produit le même message d'erreur.


Utilisation du mode de sécurité = TransportCredentialOnly

<security mode="TransportCredentialOnly">
    <transport clientCredentialType="Ntlm" />
</security>

Cela a entraîné un message d'erreur différent:

The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via

Cependant, je dois utiliser https, je ne peux donc pas changer mon schéma d'URI.


J'ai essayé d'autres combinaisons dont je ne me souviens plus, mais je les posterai quand je le ferai. Je suis vraiment à la fin des esprits ici. Je vois beaucoup de liens sur Google qui disent "Basculer vers Kerberos", mais mon serveur semble n'accepter que NTLM, pas "Négocier" (comme il le ferait s'il cherchait Kerberos), ce qui n'est malheureusement pas une option .

Toute aide là-bas, les gens?

49
Pandincus

Après beaucoup d'essais et d'erreurs, suivis par une période stagnante pendant que j'attendais une occasion de parler à nos serveurs, j'ai enfin eu l'occasion de discuter du problème avec eux et je leur ai demandé s'ils souhaitaient changer d'authentification par Sharepoint vers Kerberos.

À ma grande surprise, ils ont dit que cela ne poserait pas de problème et que c'était en fait facile à faire. Ils ont activé Kerberos et j'ai modifié mon app.config comme suit:

<security mode="Transport">
    <transport clientCredentialType="Windows" />
</security>

Pour référence, mon entrée serviceModel complète dans mon application.config ressemble à ceci:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="TestServerReference" closeTimeout="00:01:00" openTimeout="00:01:00"
             receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
             bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
             maxBufferSize="2000000" maxBufferPoolSize="2000000" maxReceivedMessageSize="2000000"
             messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
             useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                 maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="Windows" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://path/to/site/_vti_bin/Lists.asmx"
         binding="basicHttpBinding" bindingConfiguration="TestServerReference"
         contract="TestServerReference.ListsSoap" name="TestServerReference" />
    </client>
</system.serviceModel>

Après cela, tout a fonctionné comme un charme. Je peux maintenant (enfin!) Utiliser les services Web Sharepoint. Par conséquent, si quelqu'un d'autre ne parvient pas à faire fonctionner ses services Web Sharepoint avec NTLM, voyez si vous pouvez convaincre les administrateurs système de passer à Kerberos.

8
Pandincus

Visual Studio 2005

  1. Créer un nouveau projet d'application console dans Visual Studio
  2. Ajoutez une "référence Web" au service Web Lists.asmx .
    • Votre URL ressemblera probablement à: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
    • J'ai nommé ma référence Web: ListsWebService
  3. Écrivez le code dans program.cs (j'ai une liste de problèmes ici)

Voici le code.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace WebServicesConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ListsWebService.Lists listsWebSvc = new WebServicesConsoleApp.ListsWebService.Lists();
                listsWebSvc.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                listsWebSvc.Url = "http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx";
                XmlNode node = listsWebSvc.GetList("Issues");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

Visual Studio 2008

  1. Créer un nouveau projet d'application console dans Visual Studio
  2. Faites un clic droit sur Références et Ajouter une référence de service
  3. Indiquez l'URL du service Lists.asmx sur votre serveur
    • Ex: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
  4. Cliquez sur Go
  5. Cliquez sur OK
  6. Apportez les modifications de code suivantes:

Changez votre fichier app.config à partir de:

<security mode="None">
    <transport clientCredentialType="None" proxyCredentialType="None"
        realm="" />
    <message clientCredentialType="UserName" algorithmSuite="Default" />
</security>

À:

<security mode="TransportCredentialOnly">
  <transport clientCredentialType="Ntlm"/>
</security>

Changez votre fichier program.cs et ajoutez le code suivant à votre fonction principale:

ListsSoapClient client = new ListsSoapClient();
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
XmlElement listCollection = client.GetListCollection();

Ajoutez les instructions using:

using [your app name].ServiceReference1;
using System.Xml;

Référence: http://sharepointmagazine.net/technical/development/writing-caml-queries-for-retrieving-list-items-from-a-sharepoint-list

40
Kit Menke

Après de nombreuses réponses qui n'ont pas fonctionné, j'ai finalement trouvé une solution lorsque l'accès anonyme est désactivé sur le serveur IIS. Notre serveur utilise l'authentification Windows, pas Kerberos. C'est grâce à cet article de blog .

Aucune modification n'a été apportée à web.config.

Sur le serveur, le fichier .SVC du dossier ISAPI utilise MultipleBaseAddressBasicHttpBindingServiceHostFactory.

Les attributs de classe du service sont:

[BasicHttpBindingServiceMetadataExchangeEndpointAttribute]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class InvoiceServices : IInvoiceServices
{
...
}

Du côté du client, la clé qui l’a fait fonctionner était les attributs de sécurité de liaison HTTP:

EndpointAddress endpoint =
  new EndpointAddress(new Uri("http://SharePointserver/_vti_bin/InvoiceServices.svc"));
BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
InvoiceServicesClient myClient = new InvoiceServicesClient(httpBinding, endpoint);
myClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; 

(call service)

J'espère que cela fonctionne pour vous!

5
David Anderson

Si je me souviens bien, l'ajout de services Web SharePoint en tant que "Référence de service" VS2K8 pose certains problèmes. Vous devez l'ajouter en tant que "référence Web" à l'ancienne pour fonctionner correctement.

3
Jesse C. Slicer

Je voudrais essayer de vous connecter à votre site Sharepoint avec cet outil ici . Si cela fonctionne, vous pouvez être sûr que le problème vient de votre code/configuration. Cela ne résout peut-être pas votre problème immédiatement, mais cela exclut tout problème avec le serveur. En supposant que cela ne fonctionne pas, j'examinerais les points suivants:

  • Votre utilisateur a-t-il vraiment assez de droits sur le site?
  • Y a-t-il un proxy qui interfère? (Votre configuration ressemble un peu à un proxy. Pouvez-vous le contourner?)

Je pense qu'il n'y a rien de mal à utiliser le mode de sécurité Transport, mais je ne suis pas sûr du proxyCredentialType="Ntlm". Peut-être que ceci devrait être réglé sur None.

2
Stefan Egli

J'ai eu ce problème avant.

client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

faites ceci contre votre proxy wcf avant de faire l'appel.

2
bleevo

J'ai la même configuration que vous et cela fonctionne bien pour moi. Je pense que le problème réside peut-être quelque part dans votre configuration de mousse ou sur votre réseau. 

Vous avez dit que la mousse réside sur le même domaine que votre application. Si vous avez accès au site avec votre utilisateur (connecté à votre ordinateur) ... avez-vous essayé:

client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
2
matt-dot-net

J'ai eu exactement le même problème la semaine dernière - Le programme WCF se comporte étrangement sur un serveur - pourquoi?

Pour moi, la solution était plutôt simple. Sharepoint dispose de son propre ensemble d'autorisations. Mon client a essayé de se connecter en tant qu'utilisateur n'ayant pas explicitement accès au service Web via le panneau d'administration de Sharepoint.

J'ai ajouté l'utilisateur à la liste blanche et au bang de Sharepoint - cela fonctionnait.

Même si ce n'est pas le problème, veuillez noter que

La requête HTTP n’est pas autorisée avec le schéma d’authentification du client «Ntlm». L’en-tête d’authentification reçu du serveur était ‘NTLM’.

Signifie (en anglais) que vous n'avez tout simplement pas la permission. Votre protocole est probablement correct - votre utilisateur n’a tout simplement pas d’autorisations.

2
diadem

Essaye ça

<client>
  <endpoint>
    <identity>
      <servicePrincipalName value="" />
    </identity>
  </endpoint>
</client>

J'ai déjà rencontré cette erreur lorsque je travaillais dans une ferme Web et cela a été corrigé.

0
Forrest Marvez

Ce problème était encore plus étrange pour nous. Tout fonctionnait si vous aviez déjà visité le site SharePoint à partir du navigateur avant de passer l'appel SOAP. Cependant, si vous avez d'abord appelé SOAP, l'erreur ci-dessus est générée.

Nous avons pu résoudre ce problème en installant le certificat SharePoint sur le client et en ajoutant le domaine aux sites intranet locaux.

0
Glaucon