Supporto CORS all’interno dei servizi REST WCF

Ho un servizio REST WCF ospitato all’interno di un servizio Windows e vorrei inviare l’intestazione HTTP Access-Control-Allow-Origin (definita come parte di CORS ) ad ogni risposta.

Il mio tentativo di soluzione era di avere qualcosa di simile al seguente all’interno di un’implementazione di IDispatchMessageInspector :

public void BeforeSendReply(ref Message reply, object correlationState) { var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty; if (httpResponse != null) { // test of CORS httpResponse.Headers["Access-Control-Allow-Origin"] = "*"; } } 

Normalmente questo funzionerebbe, ma purtroppo il mio servizio utilizza anche l’authorization di base HTTP , il che significa che quando una richiesta arriva senza l’intestazione Authorization, WCF invia automaticamente una risposta 401 chiedendo le credenziali. Purtroppo WCF non chiama il mio IDispatchMessageInspector durante questo scambio iniziale, quindi l’intestazione Access-Control-Allow-Origin non viene aggiunta allo scambio iniziale.

Il problema si verifica quando provo a chiamare il servizio da un browser. CORS specifica che le richieste di origine incrociata dovrebbero essere consentite solo se il dominio di origine corrisponde al dominio elencato nell’intestazione di risposta Access-Control-Allow-Origin (* corrisponde a tutti i domini). Sfortunatamente, quando il browser vede la risposta iniziale 401 senza l’intestazione Access-Control-Allow-Origin, impedisce l’accesso (in base allo stesso criterio di origine ).

C’è un modo per aggiungere un’intestazione alla risposta iniziale 401 inviata automaticamente da WCF?

    Questo ragazzo mi ha salvato la giornata.

    http://blogs.microsoft.co.il/blogs/idof/archive/2011/07.aspx

    Ho intenzione di inserire alcuni dei suoi appunti qui, nel caso in cui quella pagina muoia un giorno. (Odio trovare i link “La tua risposta è giusta QUI”, e quindi il link è morto.)

                       

    Ora, devi trovare la sua libreria scaricabile chiamata “WebHttpCors.dll”.

    Ma ce n’è abbastanza (sopra) per aiutarti a raggiungere la risoluzione.

    La parte che mi ha lanciato per un ciclo (nel mio scenario) è che IE stava funzionando, ma Firefox non funzionava.

    La mia pagina di origine era:

     http://localhost:53692/test/WCFCallTestViaJQ14.htm 

    Quindi il mio servizio è a:

     http://localhost:8002/MyWCFService/MyWCFMethodByWebGet?state=NC&city=Raleigh 

    Così ho avuto localhost << - >> traffico localhost.

    **** Ma i porti erano diversi. (53692 e 8002) ****

    IE era d’accordo. Firefox non era d’accordo.

    Quindi devi ricordare che ogni browser gestisce le loro richieste .Send () in modo diverso (all’interno di JQUERY).

    Tutto ha senso ora.

     //JavaScript snipplet if (window.XMLHttpRequest) { returnObject = new XMLHttpRequest(); } else if (window.ActiveXObject) { returnObject = new ActiveXObject("Microsoft.XMLHTTP"); } else { msg = "Your browser doesn't support AJAX!"; } 

    Ecco alcune parole chiave, frasi che ho cercato su google, che alla fine mi hanno portato da qualche parte.

      Result: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.statusText]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://localhost:53692/test/WCFCallTestViaJQ14.htm :: HandleJQueryError :: line 326" data: no] XMLHttpRequest Send "NS_ERROR_FAILURE" JQuery Ajax WCF Self Hosted CORS JSON 

    Per ottenere ciò che desideri, devi gestire autonomamente l’authorization, che è ansible tramite l’impeachmenting + la registrazione di un HttpModule … lì dovresti pubblicare il 401 e con esso qualsiasi intestazione http che vuoi … c’è anche un’implementazione di esempio qui su SO: consultare Aggiunta dell’authorization HTTP di base a un servizio REST WCF

    EDIT – dopo il commento dall’OP:

    Poiché il commento dell’OP dice che è auto-hosting, la soluzione non è con HTTPModule ma in realtà con IDispatchMessageInspector.BeforeSendReply e con IDispatchMessageInspector.AfterReceiveRequest .

    L’Autorizzazione deve essere configurata su “Nessuno” e personalizzata implementata / gestita in IDispatchMessageInspector – in questo modo è ansible aggiungere qualsiasi intestazione quando si emette un 401. Altrimenti il ​​runtime che gestisce l’autenticazione di base non chiamerebbe il tuo IDispatchMessageInspector prima di Auth corretto / positivo.

    Anche se questo funziona ATTENZIONE, questo significa che tu stesso implementi il ​​codice sensibile alla sicurezza e quindi devi prendere misure appropriate per assicurarne la corretta implementazione …