2013-07-05 3 views
13

Ho un problema CORS quando SignalR self-hosting con OWIN, che si verifica solo quando provo ad abilitare l'autenticazione.Connessione tra domini SignalR con self-hosting e autenticazione

L'errore che ottengo nel mio browser web è:

XMLHttpRequest non può caricare http://.../signalr/negotiate?[snip] origine ... non è consentita da Access-Control-Allow-Origin

Questo accade solo se io attivare l'autenticazione nel mio server self-hosted utilizzando l'approccio in this answer:

public void Configuration(IAppBuilder app) 
{ 
    var listener = (HttpListener)app.Properties[typeof(HttpListener).FullName]; 
    listener.AuthenticationSchemes = AuthenticationSchemes.Ntlm; 

    app.MapHubs(new HubConfiguration { EnableCrossDomain = true }); 
} 

Se commento fuori laLineaquindi CORS funziona (e ho controllato tutto in these instructions). Ottengo lo stesso problema se utilizzo altri schemi di autenticazione di NTLM.

Utilizzando Fiddler per esaminare che cosa sta succedendo, senza autenticazione abilitato vedo le necessarie intestazioni CORS tornando dal server:

Access-Control-Allow-Credenziali: vero
Access-Control- Allow-Origin: [my server]

Tuttavia una volta abilitata l'autenticazione ottengo una risposta 401 che manca queste intestazioni. Tutte le richieste hanno l'intestazione Origin necessaria.

Dopo aver esaminato il SignalR source code, sembra che le intestazioni siano state impostate, ma presumibilmente con l'autenticazione abilitata il HttpListener sta inviando la risposta iniziale 401 senza colpire questo codice.

Quindi penso che la mia domanda è: come faccio a ottenere il HttpListener per includere un'intestazione Access-Control-Allow-Origin nella sua negoziazione dei protocolli di autenticazione?

+0

Vi siete mai andati oltre? Sto soffrendo lo stesso problema ... –

risposta

4

Ho ottenuto l'autenticazione NTLM per funzionare con signalRar di dominio incrociato ospitato in OWIN consentendo al preflight di richiedere l'accesso anonimo.

Quello che si deve fare è creare un delegato per la scelta dello schema di autenticazione che cerca le intestazioni delle richieste di preflight e le consente di farlo in modo anonimo. Tutte le altre richieste utilizzeranno NTLM.

public void Configuration(IAppBuilder appBuilder) 
{ 
    var listener = (HttpListener)appBuilder.Properties[typeof(HttpListener).FullName]; 
    listener.AuthenticationSchemeSelectorDelegate += AuthenticationSchemeSelectorDelegate; 
} 

private AuthenticationSchemes AuthenticationSchemeSelectorDelegate(HttpListenerRequest httpRequest) 
{ 
    if (httpRequest.Headers.Get("Access-Control-Request-Method")!=null) 
     return AuthenticationSchemes.Anonymous; 
    else 
     return AuthenticationSchemes.Ntlm; 
} 
+0

Grazie per il suggerimento!Sembra una strada promettente, ma il mio browser non sembra fare richieste di preflight, il che significa che in realtà non aiuta. Questo mi ha ispirato a trovare la proprietà UnsafeConnectionNtlmAuthentication, che raggiunge quasi qualcosa di simile (la prima richiesta è una risorsa che non richiede CORS e le richieste successive riutilizzano l'autenticazione dal primo). Tuttavia questo cade dopo un po 'perché le credenziali sono memorizzate nella cache per connessione TCP, e il mio client evidentemente finisce per aprire più di una connessione. Comunque è un hack. Continuerò a provare ... –

+0

Grazie mille! Mi stavo strappando i capelli cercando di farlo funzionare. –

3

presumo che si sta utilizzando Chrome, che si che queste intestazioni mancano dice molto inutilmente e che questo è il problema, quando in realtà si sono probabilmente solo dimenticato di impostare withCredentials proprietà 's tuoi XMLHttpRequest a true.

Se stai usando jQuery si può fare questo per tutte le richieste con:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) { 
    options.xhrFields = { withCredentials: true }; 
}); 

è anche bisogno di fare la cosa giusta con OPTIONS richieste come nel altra risposta.