2015-05-22 13 views
17

Sto costruendo un app angolare che interagisce con un API costruito con ASP.NET Web API 2. Sto usando l'autenticazione di base con l'invio di un header Authorization con ogni richiesta che richiede l'autenticazione:Evitare richieste opzioni di preflight con CORS

frammento angolare:

$http.defaults.headers.common['Authorization'] = authHeader; 

Richiesta:

Accept:application/json, text/javascript 
Accept-Encoding:gzip, deflate, sdch 
Accept-Language:en-US,en;q=0.8 
Access-Control-Max-Age:1728000 
Authorization:Basic [base64 encoded credential couplet here] 
Connection:keep-alive 
DNT:1 
Host: blah.com 
Origin:http://localhost:9000 
Referer:http://localhost:9000/ 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/53 

Tutto questo funziona OK, ma una richiesta di preflight OPTIONS viene inviata con ogni richiesta GET o POST. Questo ha un forte impatto sulla velocità percepita dell'applicazione. Ho letto molto su CORS "Simple Requests" e sembra che per evitare la temuta preflight OPTIONS la richiesta è di evitare di aggiungere intestazioni personalizzate nelle mie richieste. Ho provato molte altre cose come inviare un Content-Type di text/plain, ma sembra che l'intestazione di autorizzazione sia la cosa che sta violando il requisito "Richiesta semplice" CORS.

Quindi sembra che possa essere necessario spostare l'API per utilizzare l'autenticazione/autorizzazione basata su token. Per evitare richieste di verifica preliminare, sembra che avrò bisogno di posizionare il token nella stringa di query. Va bene, perché è solo una piccola applicazione web interna a cui potranno accedere solo un paio di utenti. Intendo implementare il caching sulle risposte del controller. Dal momento che ogni richiesta di un'azione del controller avrà un token diverso nella querystring basata sull'utente attualmente autenticato, questo renderà l'uso della cache inutilizzabile?

Quindi:

  1. Come evitare le richieste di verifica preliminare (utilizzando le intestazioni di autorizzazione personalizzati, se possibile)
  2. Se 1.) non è possibile, e mi trasferisco in token di autenticazione basato, sarò in grado di risposte API cache per le azioni del controller
  3. Quali sono i metodi più utilizzati per evitare richieste di verifica preliminare ma anche per autenticare gli utenti in modo sicuro?

nb So che ci sono un paio di altri thread su SO e altrove sul web per quanto riguarda questo, ma nessuno di essi tendono a fornire una risposta definitiva sul se sia possibile evitare le richieste di verifica preliminare per GET s e POST s quando si utilizzano intestazioni di autorizzazione personalizzate HTTP.

+1

1.) Non è ancora possibile attraverso tutti i browser e i metodi HTTP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests – tyler

+1

Dovresti essere in grado di utilizzare [XMLHttpRequest withCredentials] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) per inviare una richiesta non preflight con un cookie di autorizzazione. – dave

risposta

10

penso che questo post (How to apply CORS preflight cache to an entire domain) praticamente dice tutto - non c'è molto che si può fare su questo

L'unica soluzione semplice è quella di aggiungere un proxy inverso al proxy/server web che serve la vostra applicazione angolare (eg nginx) per indirizzare le chiamate RESTful attraverso lo stesso dominio, ad es appdomain.com/api -> apidomain.com.

+1

Grazie Reto! Anche se mi sarebbe piaciuto risolvere l'intera questione dei preflight in modo corretto, alla fine ho optato per questa risposta. È possibile configurare un proxy inverso in IIS e in un sito Web di Azure in modo che anche il mio client sia ospitato in un'app Web di Azure con l'inoltro delle richieste locali '/ api' nell'altra app Web di Azure che ospita l'API. Riferimento: http://ruslany.net/2014/05/using-azure-web-site-as-a-reverse-proxy/ – adaam

2

Un'altra soluzione che sembra funzionare correttamente per me. Invece di configurare un proxy e di doverlo instradare allo stesso dominio, è possibile restituire la richiesta di preflight direttamente da nginx e quindi ridurre il tempo richiesto dalla richiesta di preflight a un paio di millisecondi.

Ecco uno snippet semplice che può essere utilizzato con nginx.

location/{ 
    if ($request_method = 'OPTIONS') { 
     add_header 'Access-Control-Allow-Origin' '*'; 
     add_header 'Access-Control-Allow-Credentials' 'true'; 
     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 
     add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization'; 
     add_header 'Access-Control-Max-Age' 1728000; 
     add_header 'Content-Type' 'text/plain charset=UTF-8'; 
     add_header 'Content-Length' 0; 
     return 204; 
    } 
} 

Una volta che la richiesta di verifica preliminare è successo, è quindi possibile semplice add "Access-Control-Allow-Origin" e altre cose necessarie per 'Get', le richieste di 'post', ecc ...