10

Ho creato un backend API REST con Spring MVC e protetto con Auth base con Spring Security.Chiamata di autenticazione di base tra domini JQuery

Mi piacerebbe fare una chiamata ajax cross domain all'API REST dai client Javascript. Non voglio usare JSONP perché non voglio essere limitato alle chiamate GET. Io uso CORS e ho messo le intestazioni giuste sul lato server.

Supponiamo che la mia API REST si trovi sul dominio localhost: 8087 e il mio client su localhost: 8086, che è una chiamata interdominio.

nel mio client JavaScript, faccio chiamata AJAX con jQuery:

<script> 
     $.ajax ({ 
      url: "http://localhost:8087/SpringMVC/users/user1", 
      beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); }, 
      success: function(val) { console.log(val); alert("success" + val); }, 
      error: function(val) { console.log(val); alert("error" + val); } 
     }); 
</script> 

mio problema è che jQuery non invia l'intestazione di autorizzazione nella richiesta HTTP e non so perché. Non capisco perché lo faccio nel metodo beforeSend, quindi dovrebbe essere all'interno della richiesta HTTP. Risultato: ho un errore 401.

Quando provo lo script dallo stesso dominio localhost: 8087, che non è più il dominio incrociato, non ho alcun problema.

Com'è possibile?

Il mio script è solo un test. Non intendo mettere il mio nome utente/password sul lato client. Ma voglio testare come eseguire chiamate ajax su un'API REST protetta di base. Immagino di dover inviare sul lato server per proteggere il mio nome utente/password, l'API REST mi restituisce un cookie e non ho più bisogno di passare il nome utente/password per le mie prossime chiamate ajax all'API REST. Ho ragione ?

Ho testato la mia API REST con il client Chrome Advanced REST e funziona così. Per la prima richiesta ho bisogno di passare l'intestazione di autorizzazione. Quindi non è necessario. Dovrebbe funzionare anche così con il mio client web javascript? Intendo usare Node.JS con Backbone per costruirlo.

Grazie mille.

EDIT2: Sembra davvero un problema con il browser CORS. Ho aggiunto l'intestazione Access-Control-Allow-Methods per il metodo OPTIONS sul lato server e funziona su Chrome. Ho accesso alla risposta JSON senza errori più. Ma ho ancora bisogno di usare l'intestazione di autorizzazione per le prossime richieste. Come dire a jQuery di usare il cookie inviato?

e quando provo con Firefox 11, non ho accesso alla risposta JSON e ho l'errore:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1" 
+0

Sei codificato in base64 per nome utente/password? –

+0

Sì, l'ho messo xxxxxxxx invece del nome utente reale: password. – rico

risposta

8

A quanto pare, Chrome e Firefox trattano tra domini richiede un po 'diverso. Prima di eseguire la richiesta di dominio incrociato, fanno quella che viene chiamata una richiesta di "preflight" con il metodo HTTP OPTIONS. La differenza tra Chrome e Firefox è che Chrome invia anche l'intestazione Autorizzazione con le credenziali, mentre Firefox no.

Quindi, rimane un problema di configurazione Spring Security. Il mio URL/utenti/* è protetto per tutti i metodi HTTP, incluse le OPZIONI. Nel caso di Firefox, poiché l'intestazione di autorizzazione non viene inviata, la mia richiesta non è autorizzata. Se limito il mio url/users/* sicuro solo al metodo GET, allora funziona perfettamente per Firefox.Così ho dovuto solo aggiungere che nel mio Primavera configurazione della sicurezza:

<intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()" method="GET"/> 

In seguito, ho la scelta: posso aggiungere altri metodi per essere depositati che l'intercetta-url, tranne OPZIONI, o posso limitare il HTTP chiamata metodo a GET nel mio controller MVC Spring, che gestirà anche le mie chiamate OPTIONS secondo Javadoc. Ho scelto la seconda soluzione. Ma se qualcuno trova una soluzione per forzare Firefox ad inviare credenziali come Chrome, sarebbe fantastico e io sceglierei questo.

2

Un'altra opzione per lo scenario di configurazione Primavera di sicurezza presentato dal rico sarebbe:

<http ... use-expressions="true"> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="permitAll" method="OPTIONS"/> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()"/> 
    ... 
</http> 

HTTP OPZIONI richieste saranno sempre passare attraverso l'autenticazione e qualsiasi altro metodo HTTP non lo faranno.

Nota l'attributo use-expressions XML impostato vero in <http> elemento. Primavera di sicurezza sarà poi aspettare i access attributi degli elementi <intercept-url> per contenere primavera espressioni EL, come permitAll e isAuthenticated().

Problemi correlati