2012-03-30 8 views
5

Mam problem z usługą WCF z uwierzytelnianiem systemu Windows na jednym z serwerów, na których go wdrażam (jest to komputer z systemem Windows Server 2008 R2), ale działa bezbłędnie na wszystkich innych komputerach, do których mam dostęp (Windows 7, Windows Server 2008 i Windows Server 2008 R2). Udało mi się odtworzyć problem za pomocą naprawdę prostej przykładowej aplikacji, która mniej lub bardziej całkowicie wyklucza mój kod jako przyczynę problemu.Nieudane wykonanie adresu URL podczas wywoływania usługi WCF z uwierzytelnianiem systemu Windows

Minimalna aplikacja mogę odtworzyć problem ze jest niewielka modyfikacja szablonu projektu usług WCF:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    string GetData(int value); 
} 

[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)] 
public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     return string.Format("You entered: {0}\nUsername: {1}", 
      value, 
      ServiceSecurityContext.Current == null ? 
       "<null>" : 
       ServiceSecurityContext.Current.PrimaryIdentity.Name); 
    } 
} 

Zasadniczo włączona kompatybilność ASP.NET (muszę, bo rzeczywisty kod wykorzystuje HttpHandler dla uwierzytelnianie) i zwracana jest nazwa użytkownika uwierzytelnionego użytkownika.

Zawartość web.config są następujące:

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <compilation debug="true" targetFramework="4.0" /> 
    <authentication mode="Windows"/> 
    </system.web> 
    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="ServiceBehavior"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="HttpWindowsBinding" maxReceivedMessageSize="2147483647"> 
      <readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647" maxDepth="2147483647"/> 
      <security mode="TransportCredentialOnly"> 
      <transport clientCredentialType="Windows" /> 
      </security> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" /> 
    <services> 
     <service name="TestService.Service1" behaviorConfiguration="ServiceBehavior"> 
     <endpoint address="" 
        binding="basicHttpBinding" 
        bindingConfiguration="HttpWindowsBinding" 
        contract="TestService.IService1" /> 
     <endpoint address="problem" 
        binding="basicHttpBinding" 
        bindingConfiguration="HttpWindowsBinding" 
        contract="TestService.IService1" /> 
     </service> 
    </services> 
    </system.serviceModel> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    </system.webServer> 
</configuration> 

zauważy dwa punkty końcowe: jeden z domyślnym adresem, drugi ze względnym adresem. Wywołanie pierwszy udaje się nawet na serwerze problematycznej, natomiast rozmowa z drugim nie powiedzie się z następującym błędem:

Exception type: HttpException 
Exception message: Failed to Execute URL. 
at System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.BeginExecuteUrl(String url, String method, String childHeaders, Boolean sendHeaders, Boolean addUserIndo, IntPtr token, String name, String authType, Byte[] entity, AsyncCallback cb, Object state) 
at System.Web.HttpResponse.BeginExecuteUrlForEntireResponse(String pathOverride, NameValueCollection requestHeaders, AsyncCallback cb, Object state) 
at System.Web.DefaultHttpHandler.BeginProcessRequest(HttpContext context, AsyncCallback callback, Object state) 
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) 

Wezwanie tylko zawodzi, gdy używany jest klasyczny rurociąg (muszę ją ze względu na HttpHandler, ale problem można odtworzyć nawet bez niego). Dzięki zintegrowanemu rurociągowi problem już minął. Ponadto, jeśli wyłączę uwierzytelnianie systemu Windows, problem również minął:

<binding name="HttpBinding" maxReceivedMessageSize="2147483647"> 
    <readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647" maxDepth="2147483647"/> 
    <security mode="None"> 
    <transport clientCredentialType="None" /> 
    </security> 
</binding> 

Zauważyłem inny szczegół z zarejestrowanym HttpHandler. Wartość właściwości HttpRequest.CurrentExecutionFilePath dla punktu końcowego z adresem względnym różni się między problematycznym serwerem (~/Service1.svc/problem) a działającymi serwerami (~/Service1.svc). Chociaż nie jestem dobrze zaznajomiony z IIS, podejrzewam, że może to wskazywać na przyczynę problemu - może coś związanego z routingiem żądań?

Brakuje mi pomysłów, dlatego zamieszczam to tutaj w nadziei, że ktoś rozpozna, jaki może być problem. Wszelkie sugestie są mile widziane.

+1

Czy masz włączone przepisywanie adresów URL w IIS? To pachnie jak pewnego rodzaju pozwolenie. [Jaka jest różnica między klasycznym i zintegrowanym trybem potoku w IIS7?] (Http://stackoverflow.com/questions/3062709/what-is-the-difference-between-classic-and-integrated-pipeline-mode-in- iis7) Może być pomocne. –

+0

@PetarVucetin Sprawdziłem i przepisywanie adresów URL nie jest włączone na serwerze.Chociaż twój komentarz nie odpowiedział dokładnie na moje pytanie, podany link dał mi kilka pomysłów - udało mi się przekonfigurować moją aplikację, aby działała ze zintegrowanym trybem potoku, w którym problem się nie objawia. Nadal chciałbym wiedzieć, jak sprawić, by działało w klasycznym trybie potokowym, ale jeśli nie dostanę lepszej odpowiedzi wyjaśniającej, że dla mnie, twój komentarz jest najlepszym kandydatem do nagrody. W końcu udało mi się rozwiązać natychmiastowy problem. –

+0

Dzięki Damir. Kiedy mam trochę czasu, mogę spróbować naprawić ten problem. Po prostu łaskocze moją debugowanie kości ... –

Odpowiedz

0

Problem może być adres „~/Service1.svc/problem”

Gdy adres jest „~/Service1.svc” wezwanie uderza plik SVC i wykorzystuje te informacje w pliku, aby znaleźć interfejs, a następnie konfiguracja dla tego interfejsu.

Gdy używasz względnego adresu bez pliku svc, sprawdza adres w pliku konfiguracyjnym.

Czy posiadasz katalog "Service1.svc" na jednym z serwerów, czy jest to adres bez ".svc" na serwerze, na którym działa?

+0

Ani. Podczas rozwiązywania problemów w celu testowania utworzyłem nową aplikację na wszystkich serwerach z plikami z powyższego projektu testowego: 'Service1.svc',' Web.config', 'bin \ TestService.dll'. –

1

Czy masz włączone przepisywanie adresów URL w IIS? To pachnie jak pewnego rodzaju pozwolenie. What is the difference between Classic and Integrated pipeline mode in IIS7? Może być pomocne.

+0

Dzięki za link. Dzięki niemu przeczytałem o różnicach i ostatecznie udało mi się sprawić, aby moja aplikacja działała w trybie zintegrowanego potoku. Wciąż jestem ciekawy, dlaczego nie działa w klasycznym trybie potokowym na tym serwerze. –

Powiązane problemy