5

Für SharePoint 2010 haben wir benutzerdefinierte Webdienste (NICHT SOAP!) Verwendet, um einige Drittanbieterdaten für JS-Code auf den vom Browser angezeigten Seiten verfügbar zu machen. Dies waren sensible Daten, daher verwendeten wir Identitätswechsel, um sicherzustellen, dass nur die richtigen Benutzer darauf zugreifen konnten. Unsere Lösung funktioniert in SharePoint 2013 nicht mehr. Da die ursprüngliche Lösung ziemlich komplex ist, habe ich in SP 2013 einen kleinen und einfachen Dienst erstellt, um zu untersuchen, wie ein Webdienst mit Identitätswechsel eingerichtet werden kann. Der Dienst wird in einem Unterordner von ISAPI bereitgestellt.Benutzerdefinierter Webdienst in SharePoint 2013 mit Identitätswechsel

Dies ist die Grundlage, ohne Identitätswechsel, die funktioniert:

TestService.svc:

<%@ ServiceHost 
    Language="C#" 
    Debug="true" 
    Service="Sandbox.TestService, $SharePoint.Project.AssemblyFullName$" 
    CodeBehind="TestService.svc.cs" 
    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 

Der Code hinter in TestService.svc.cs ist:

using Microsoft.SharePoint.Client.Services; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel.Activation; 
using System.ServiceModel; 
using System.ServiceModel.Web; 

namespace Sandbox 
{ 
    [ServiceContract] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
    public class TestService 
    { 
     [OperationContract] 
     [WebGet(UriTemplate = "GetAllNumbers", 
      ResponseFormat = WebMessageFormat.Json)] 
     List<int> GetAllNumbers() 
     { 
      List<int> result = new List<int>(); 
      result.AddRange(new[] { 1, 1, 2, 3, 5, 8, 13 }); 
      return result; 
     } 
    } 
} 

Wenn ich auftrete ein GET auf http://pc00175/_vti_bin/Sandbox/TestService.svc/GetAllNumbers Ich erhalte die erwartete Resonanz [1,1,2,3,5,8,13]. Gut so weit. Jetzt versuche ich den Identitätswechsel zu verwenden: „Eine anonyme Identität kann keinen Identitätswechsel durchführt“

using Microsoft.SharePoint.Client.Services; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel.Activation; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Security.Principal; 

namespace Sandbox 
{ 
    [ServiceContract] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
    public class TestService 
    { 
     [OperationContract] 
     [WebGet(UriTemplate = "GetAllNumbers", 
      ResponseFormat = WebMessageFormat.Json)] 
     List<int> GetAllNumbers() 
     { 
      List<int> result = new List<int>(); 
      WindowsImpersonationContext ctx = ServiceSecurityContext.Current.WindowsIdentity.Impersonate(); 
      try 
      { 
       result.AddRange(new[] { 1, 1, 2, 3, 5, 8, 13 }); 
      } 
      finally 
      { 
       ctx.Undo(); 
      } 
      return result; 
     } 
    } 
} 

Jetzt erhalte ich eine System.InvalidOperationException mit der Meldung wenn Sie den Anruf an ServiceSecurityContext.Current.WindowsIdentity.Impersonate() tätigen. Ich muss dem WCF mitteilen, dass wir für diesen Anruf einen Identitätswechsel benötigen. So habe ich ein Attribut [OperationBehavior(Impersonation=ImpersonationOption.Required)]:

using Microsoft.SharePoint.Client.Services; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel.Activation; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Security.Principal; 

namespace Sandbox 
{ 
    [ServiceContract] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
    public class TestService 
    { 
     [OperationContract] 
     [WebGet(UriTemplate = "GetAllNumbers", 
      ResponseFormat = WebMessageFormat.Json)] 
     [OperationBehavior(Impersonation=ImpersonationOption.Required)] 
     List<int> GetAllNumbers() 
     { 
      List<int> result = new List<int>(); 
      WindowsImpersonationContext ctx = ServiceSecurityContext.Current.WindowsIdentity.Impersonate(); 
      try 
      { 
       result.AddRange(new[] { 1, 1, 2, 3, 5, 8, 13 }); 
      } 
      finally 
      { 
       ctx.Undo(); 
      } 
      return result; 
     } 
    } 
} 

Jetzt finde ich die folgende Fehlermeldung in dem Sharepoint-Protokoll:

Error when open web service: System.InvalidOperationException: The contract operation 'GetAllNumbers' requires Windows identity for automatic impersonation. A Windows identity that represents the caller is not provided by binding ('WebHttpBinding','http://tempuri.org/') for contract ('TestService','http://tempuri.org/'.  at System.ServiceModel.Dispatcher.SecurityValidationBehavior.WindowsIdentitySupportRule.ValidateWindowsIdentityCapability(Binding binding, ContractDescription contract, OperationDescription operation)  at System.ServiceModel.Dispatcher.SecurityValidationBehavior.WindowsIdentitySupportRule.Validate(ServiceDescription description)  at System.ServiceModel.Dispatcher.SecurityValidationBehavior.System.ServiceModel.Description.IServiceBehavior.Validate(ServiceDescriptio... 

Dann nahm ich an, dass ich neben TestService.svc eine web.config hinzugefügt hatte und TransportCredentialsOnly Modus hinzufügen, aber das half nicht:

<?xml version="1.0"?> 
<configuration> 
    <system.serviceModel> 
    <bindings> 
     <webHttpBinding> 
     <binding> 
      <security mode="TransportCredentialOnly"> 
      <transport clientCredentialType="Ntlm"/> 
      </security> 
     </binding> 
     </webHttpBinding> 
    </bindings> 
    </system.serviceModel> 
</configuration> 

ich bekomme die gleichen Fehler in der Sharepoint-Protokolldatei.

Ich hoffe jemand hat einen Tipp für mich.

Vielen Dank für das Lesen dieser weit!

Peter

Antwort

0

Wenn Sie verwenden möchten, REST, warum Sie nicht einfach eine App für diese erstellen? Das ist viel einfacher, als einen WCF-Dienst in SharePoint verfügbar zu machen. Sie können dann Ihre eigenen Sicherheitseinstellungen konfigurieren. Diese article sollte Ihnen dabei helfen.

+0

Vielen Dank für den Hinweis. Ich habe einen Fehler gemacht und es als REST-Service beschrieben. Es ist ein allgemeiner Webservice. Wir möchten die gesamte Lösung nicht neu gestalten, da sie ziemlich komplex ist und wir möchten, dass die SharePoint 2010- und 2013-Lösungen so ähnlich wie möglich bleiben. –

Verwandte Themen