28

Ho un server basato su REST che sto cercando di comunicare con JQuery. Sia XML che JSON sono disponibili come formati di risposta, quindi sto usando JSON.JQuery chiamate Ajax con autenticazione di base HTTP

I collegamenti sono tutti SSL in modo autenticazione di base HTTP è stato il nostro metodo di autorizzazione di scelta, e non abbiamo avuto problemi con gli altri front-end (crudo Javascript, Silverlight, etc ...)

Ora sto cercando mettere insieme qualcosa con JQuery e avere problemi infiniti usando l'autenticazione di base HTTP.

ho perlustrato attraverso numerose domande precedenti la maggior parte delle quali hanno o soluzioni che non sembrano funzionare in atto o la colpa l'intero problema sull'accesso origine croce, che ho già superato nel test di base Javascript. Le risposte forniscono sempre Access-Control-Allow-Origin impostato sull'intestazione Origin fornita nella richiesta e questo può essere visualizzato nelle risposte dei miei test.

in JavaScript di base, questo intero chiamata è molto semplice realizzato con:

req.open('GET', 'https://researchdev-vm:8111/card', true, 'test', 'testpassword'); 

Il tentativo JQuery a questo è piuttosto standard:

 $.ajax({ 
     username: 'test', 
     password: 'testpassword', 
     url: 'https://researchdev-vm:8111/card', 
     type: 'GET', 
     dataType: 'json', 
     crossDomain: true, 
     /*data: { username: 'test', password: 'testpassword' },*/ 
     beforeSend: function(xhr){ 
      xhr.setRequestHeader("Authorization", 
       //"Basic " + encodeBase64(username + ":" + password)); 
       "Basic AAAAAAAAAAAAAAAAAAA="); 
     }, 
     sucess: function(result) { 
      out('done'); 
     } 
    }); 

L'unico metodo che sembra effettivamente funzionare per fornire l'autenticazione è l'inserimento diretto dei dati codificati Base64 nella funzione beforeSend(). Se questo non è incluso, non ci sono progressi fatti di sorta. Le proprietà di nome utente e password sembrano essere completamente ignorate.

Con il comportamento beforeSend() fornito, la chiamata GET ottiene una risposta positiva con i dati inclusi. Tuttavia, poiché si tratta di una chiamata cross-site, una chiamata OPTIONS viene eseguita prima della chiamata GET e fallisce sempre, poiché non utilizza beforeSend() e pertanto ottiene una risposta 401 a causa dell'autenticazione non riuscita.

C'è un modo migliore per realizzare ciò che dovrebbe essere una chiamata molto banale? Il fatto che la richiesta OPTIONS non utilizzi l'elaborazione della funzione beforeSend() può essere considerata un bug? C'è forse un modo per disattivare completamente il controllo OPTIONS? Non è possibile effettuare questa chiamata non cross-site, poiché JavaScript sembra considerare anche un numero di porta diverso sulla stessa macchina di "cross-site".

+0

Non avere la prima di inviare ei campi nome utente/password . Rimuoverei i campi username/password dalla funzione $ .ajax. –

risposta

1

Ecco qualcosa che funge da autenticazione pass-through per le chiamate AJAX. Questo si basa su NTLM per l'autenticazione nella pagina da cui verrà eseguito il javascript. Forse questo ti aiuterà a: Codice

PHP:

<?php 
$headers = apache_request_headers(); 
if (isset($headers['Authorization'])) 
    echo "<script>var auth = " . $headers['Authorization'] . "</script>"; 
unset($headers); 
?> 

utilizzando jQuery si può usare in questo modo:

$.ajax({ 
     type: 'POST', 
     url: './somePage.php', 
     data: {"test":true}, 
     dataType: 'json', 
     success: function(data) { 
      console.log(data.username); 
     }, 
     beforeSend : function(req) { 
      req.setRequestHeader('Authorization', auth); // <<<<----- USED HERE 
     }, 
}); 

Per XMLHttpRequest di serie:

var xml = new XMLHttpRequest(); 
xml.open('GET', './somePage.php', true); 
xml.setRequestHeader('Authorization', auth); // <<<<----- USED HERE 
xml.send(); 
+0

Sarebbe utile se tu fornissi un esempio di come sarebbe la variabile 'auth'. Immagino sia un oggetto con proprietà utente e password, ma sarebbe meglio essere espliciti su quello – TKoL

+0

@TKoL L'OP fornisce un esempio del valore 'auth'. Essenzialmente, è: '" Basic "+ encodeBase64 (username +": "+ password));' –

+0

grazie @ wes.hysell. Per me era non ovvio. – TKoL

3

questa domanda è probabilmente oltre la sua data di scadenza, ma stavo lavorando con la stessa cosa con Jquery e mi sono imbattuto nella s problema

Gli attributi nome utente e password non sembrano eseguire una codifica base64 del nome utente/password come per l'autenticazione di base HTTP.

Guardate le seguenti richieste (abbreviata per brevità), in primo luogo utilizzando i parametri di "password" nel metodo JQuery AJAX "username" e:

Request URL:http://testuser%40omnisoft.com:[email protected]:60023/Account 
Request Method:GET 
Accept:application/json, text/javascript, */*; q=0.01 
Host:localhost:60023 

E ora con il metodo beforeSend:

Request URL:http://localhost:60023/Account 
Request Method:GET 
Accept:application/json, text/javascript, */*; q=0.01 
Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ= 
Host:localhost:60023 

Si noti che il primo metodo non include un'intestazione "Autorizzazione" nella richiesta, ma invece prefigura l'URL di destinazione. Non sono esperto sull'autenticazione di base HTTP, ma indicherebbe che il primo non è un'implementazione corretta e quindi non riesce (o almeno lo fa con l'implementazione del mio server).

Per quanto riguarda la richiesta OPZIONI con JSONP, è possibile provare a utilizzare ?callback=? nell'URL anziché utilizzare l'opzione crossdomain, solo per essere espliciti.

1

Per chi ha riscontrato questo problema, ho risolto il problema intercettando le richieste OPTIONS con Apache e inoltrando solo GET e POST al back-end.

Questa soluzione è appserver indipendente e lavora quindi per PHP e Java così:

<VirtualHost *:80> 

    # ServerName and other configuration... 


    # CORS 
    Header set Access-Control-Allow-Origin "*" 
    Header set Access-Control-Allow-Methods "OPTIONS, GET, PUT, POST" 
    Header set Access-Control-Allow-Headers "Authorization" 

    # Intercept OPTIONS calls 
    RewriteEngine On 
    RewriteCond %{REQUEST_METHOD} ^(OPTIONS)$ 
    RewriteRule .* - [L] 

    # Backend, adapt this line to fit your needs 
    RewriteRule /(.*) ajp://localhost:8010/$1 [L,P] 

</VirtualHost> 

Saluti, Maurizio

+0

Per un'implementazione REST corretta, probabilmente vorrai includere anche il metodo 'PUT'. –

+0

debolmente, grazie Jezen! – Maurix