2015-09-23 9 views
11

Con il mio setup NGinx sono stato in grado di intercettare le richieste OPTIONS da un preflight di ajax e rispondere con le intestazioni CORS corrette e una risposta di 200 in modo che la richiesta potesse proseguire in avanti. Sto tentando di consolidare i miei proxy di frontend in HAProxy e sto avendo alcuni problemi nel far funzionare questo pezzo del puzzle.HAProxy CORS OPTIONS setup intercetta intestazione

Il mio problema particolare è che mentre sono in grado di aggiungere le corrette opzioni CORS quando c'è un server in grado di rispondere correttamente a una richiesta OPTIONS, alcuni dei backend non possono gestire/rispondere con un errore 405 quando la richiesta di preflight è rilasciato Il mio haproxy.cfg incluse le seguenti righe per aggiungere le intestazioni:

capture request header origin len 128 
http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if { capture.req.hdr(0) -m found } 
rspadd Access-Control-Allow-Credentials:\ true if { capture.req.hdr(0) -m found } 
rspadd Access-Control-Allow-Headers:\ Origin,\ X-Requested-With,\ Content-Type,\ Origin,\ User-Agent,\ If-Modified-Since,\ Cache-Control,\ Accept if { capture.req.hdr(0) -m found } 
rspadd Access-Control-Allow-Methods:\ GET,\ POST,\ PUT,\ DELETE,\ OPTIONS if { capture.req.hdr(0) -m found } 
rspadd Access-Control-Max-Age:\ 1728000 if { capture.req.hdr(0) -m found } 

la soluzione data a:

How to send a response with HAProxy without passing the request to web servers opere quando si impostano tutte le intestazioni corrette da richiesta di un cliente, ma non è dinamica, che è non è una soluzione ideale.

Qualsiasi aiuto sarebbe apprezzato!

+0

Sto ottenendo [2016-04-19 12: 49: 54.625] uaa - 5213 [http-bio-8080-exec-5] .... DEBUG --- CorsFilter: elaborazione CORS completata per: URI:/login.do; Schema: https; Host: uaa.testinception25.io; Porta: 443; Origine: https://skyfallui-testinception25.com; Metodo: POST Status: 403 Aiutatemi l'impostazione haproxy per questo –

risposta

3

È possibile utilizzare Lua, ma è necessario assicurarsi che HAproxy sia stato creato con USE_LUA, selezionando haproxy -vv.

Questo è un esempio di configurazione, non l'ho provato io stesso, ma vi darà un'idea di cosa si può fare:

# haproxy.cfg 

global 
    lua-load cors.lua 

frontend foo 
    ... 
    http-request use-service lua.cors-response if METH_OPTIONS { req.hdr(origin) -m found } { ... } 

# cors.lua 
core.register_service("cors-response", "http", function(applet) 
    applet:set_status(200) 
    applet:add_header("Content-Length", "0") 
    applet:add_header("Access-Control-Allow-Origin", applet.headers["origin"][0]) 
    applet:add_header("Access-Control-Allow-Credentials", "true") 
    applet:add_header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Origin, User-Agent, If-Modified-Since, Cache-Control, Accept") 
    applet:add_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") 
    applet:add_header("Access-Control-Max-Age", "1728000") 
    applet:start_response() 
end) 
2

Basato sul great answer from anine.io mi si avvicinò con la seguente soluzione che consente di definire un elenco di origini consentite e aggiunge anche l'intestazione mancante Acccess-Control-Allow-Origin per tutte le richieste HTTP. La risposta di anine.io ha mostrato solo il preflight CORS, ma non ha considerato le richieste normali.

Nel haproxy.cfg carico file cors.lua (adattare il percorso se necessario) nella sezione globale

global 
    lua-load /usr/local/etc/haproxy/cors.lua 

Aggiungere la configurazione CORS alla definizione di frontend

frontend http-in 
    # CORS configuration 
    # capture origin HTTP header 
    capture request header origin len 128 
    # add Access-Control-Allow-Origin HTTP header to response if origin matches the list of allowed URLs 
    http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if !METH_OPTIONS { capture.req.hdr(0) -m reg -f /usr/local/etc/haproxy/cors-origins.lst } 
    # if a preflight request is made, use CORS preflight backend 
    http-request use-service lua.cors-response if METH_OPTIONS { capture.req.hdr(0) -m reg -f /usr/local/etc/haproxy/cors-origins.lst } 

Creare un file denominato cors.lua e memorizzare sotto il percorso specificato sopra. Il file contiene il preflight CORS e, se non ci sono buoni motivi, non limitare Metodi o Intestazioni perché dovresti includere eventuali restrizioni riguardanti i metodi o le intestazioni negli ACL definiti nella configurazione CORS in haproxy.conf. Note: Currently Browsers do not support wildcard * for the Access-Control-Allow-Methods header. Il file cors.lua deve contenere il seguente contenuto

core.register_service("cors-response", "http", function(applet) 
    applet:set_status(200) 
    applet:add_header("Content-Length", "0") 
    applet:add_header("Access-Control-Allow-Origin", applet.headers["origin"][0]) 
    applet:add_header("Access-Control-Allow-Credentials", "true") 
    applet:add_header("Access-Control-Allow-Headers", "*") 
    applet:add_header("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS") 
    applet:add_header("Access-Control-Max-Age", "1728000") 
    applet:start_response() 
end) 

Creare un file denominato cors-origins.lst e memorizzarlo nel percorso specificato sopra nella configurazione CORS. Il file dovrebbe contenere espressioni regolari (o semplicemente stringhe). Se il client invia un'intestazione Origin, verrà convalidato contro queste espressioni regolari e solo se corrispondono, verrà restituita la verifica preliminare CORS da cors.lua (per le richieste HTTP OPTIONS) o Access-Control-Allow-Origin con il valore dell'intestazione di origine della richiesta del client. essere aggiunto alla risposta. Un esempio del contenuto di cors-origins.lst potrebbe essere

example.com 
localhost.* 
.*\.mydomain\.com:[8080|8443] 

Verificare la configurazione con http://test-cors.org/. Per le richieste GET non dovrebbe esserci preflight CORS.Per richieste diverse da GET, una richiesta di verifica preliminare CORS deve essere eseguita dal client per prima (ad esempio una chiamata HTTP OPTIONS) per verificare se è consentito il metodo, le intestazioni e l'autorizzazione previsti.

Vedere HTTP access control (CORS) per ulteriori dettagli su CORS.

2

Voglio lanciare la mia risposta sul ring qui. Abbiamo attraversato un bel po 'di dolore per arrivare a un setup di lavoro. Le altre risposte a questa domanda sono state molto utili, ma non ci hanno dato una configurazione pienamente funzionante.

Volevamo consentire qualsiasi origine. Se hai bisogno di origini autorizzate, consulta lo answer from @Florian Feldhaus per un utile trucco regex. Invece di utilizzare una whitelist, abbiamo eco di nuovo l'intestazione posizione:

http-request set-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if { capture.req.hdr(0) -m found }

Abbiamo anche bisogno di impostare in modo esplicito Access-Control-Allow-Headers e Access-Control-Expose-Headers. Browser support for wildcards in theses headers is not quite there yet.

Quindi, ecco cosa fa la nostra configurazione:

  1. gestisce le richieste di verifica preliminare utilizzando this cors.lua script
  2. gestisce richiesta normale utilizzando http-response set-header aggiungere Access-Control-Allow- * intestazioni
  3. regolare tune.maxrewrite per adattarsi alle nostre CORS intestazioni (che sono> 1 KB)

I passaggi per 1) e 2) sono spiegati nelle altre risposte qui, ma il passaggio 3) ci ha messo molto tempo per capire. Ho documentato la configurazione completa e il viaggio che ci ha portato lì in this blog post. Il post contiene collegamenti al gist su github.