Ho un problema con un servizio WCF che utilizza l'autenticazione di Windows su uno dei server in cui lo sto distribuendo (è una macchina Windows Server 2008 R2), mentre funziona in modo impeccabile su tutte le altre macchine a cui ho accesso (Windows 7, Windows Server 2008 e Windows Server 2008 R2). Sono riuscito a riprodurre il problema con un'applicazione di esempio veramente semplice che esclude più o meno completamente il mio codice come causa del problema.Impossibile eseguire l'URL quando si chiama un servizio WCF con l'autenticazione di Windows
La domanda minima posso riprodurre il problema con una piccola modifica del modello di progetto servizio 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);
}
}
Fondamentalmente abilitato compatibilità ASP.NET (ho bisogno perché il codice effettivo utilizza un HttpHandler per autenticazione) e viene restituito il nome utente dell'utente autenticato.
I contenuti di web.config
sono i seguenti:
<?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>
dati i due punti finali: una con l'indirizzo predefinito, l'altro con un indirizzo relativo. Chiamando il primo esito positivo anche sul server problematico, mentre la chiamata alla seconda non riesce con errore seguente:
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)
la chiamata non riesce solo se si utilizza la pipeline classico (ne ho bisogno a causa della HttpHandler, ma il problema può essere riprodotto anche senza di esso). Con la pipeline integrata il problema è finito. Anche se disattivare l'autenticazione di Windows, il problema è andato così:
<binding name="HttpBinding" maxReceivedMessageSize="2147483647">
<readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647" maxDepth="2147483647"/>
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
Ho notato un altro dettaglio con una HttpHandler registrati. Il valore della proprietà HttpRequest.CurrentExecutionFilePath per l'endpoint con l'indirizzo relativo è diverso tra il server problematico (~/Service1.svc/problem
) ei server di lavoro (~/Service1.svc
). Anche se non ho molta familiarità con IIS, sospetto che questo possa suggerire la causa del problema, forse qualcosa legato al routing delle richieste?
Sono a corto di idee quindi sto postando questo qui nella speranza che qualcuno riconoscerà quale potrebbe essere il problema. Qualsiasi suggerimento è benvenuto.
Hai la riscrittura dell'URL su IIS attivata? Questo odora di un problema di autorizzazione di qualche tipo. [Qual è la differenza tra la modalità pipeline classica e integrata in IIS7?] (Http://stackoverflow.com/questions/3062709/what-is-the-difference-between-classic-and-integrated-pipeline-mode-in- 7) Potrebbe essere utile. –
@PetarVucetin Ho controllato e la riscrittura dell'URL non è abilitata sul server.Anche se il tuo commento non ha risposto esattamente alla mia domanda, il link che mi hai fornito mi ha dato alcune idee: sono riuscito a riconfigurare la mia applicazione per farlo funzionare con la modalità pipeline integrata dove il problema non si manifesta. Mi piacerebbe ancora sapere come farlo funzionare in modalità pipeline classica, ma se non ottengo una risposta migliore chiarendo che per me, il tuo commento è il miglior candidato per la taglia. Mi ha fatto risolvere il problema immediato, dopotutto. –
Grazie Damir. Quando avrò un po 'di tempo, posso provare a riprodurre il problema. Mi fa il solletico al mio osso di debug ... –