Usa l'autenticazione di base con jQuery e Ajax


419

Sto cercando di creare un'autenticazione di base tramite il browser, ma non riesco davvero ad arrivarci.

Se questo script non sarà presente, l'autenticazione del browser prenderà il sopravvento, ma voglio dire al browser che l'utente sta per effettuare l'autenticazione.

L'indirizzo dovrebbe essere qualcosa del tipo:

http://username:password@server.in.local/

Ho un modulo:

<form name="cookieform" id="login" method="post">
      <input type="text" name="username" id="username" class="text"/>
      <input type="password" name="password" id="password" class="text"/>
      <input type="submit" name="sub" value="Submit" class="page"/>
</form>

E una sceneggiatura:

var username = $("input#username").val();
var password = $("input#password").val();

function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = Base64.encode(tok);
  return "Basic " + hash;
}
$.ajax
  ({
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '{"username": "' + username + '", "password" : "' + password + '"}',
    success: function (){
    alert('Thanks for your comment!');
    }
});

6
Quindi non vuoi che il browser gestisca l'autenticazione BASIC? Perché non usare solo l'autenticazione basata su form?
no.good.at.coding

@ no.good.at.coding Se devi integrarti con un'API di terze parti dietro l'autenticazione (che è quello che sto cercando di fare - developer.zendesk.com/rest_api/docs/core/… )
Brian Hannay

Risposte:


467

Utilizzare il beforeSendcallback di jQuery per aggiungere un'intestazione HTTP con le informazioni di autenticazione:

beforeSend: function (xhr) {
    xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},

6
sto usando l'esempio che hai dato ma non funziona `$ .ajax ({url:" server.in.local / index.php ", beforeInvia: function (xhr) {xhr.setRequestHeader (“ Authorization ”,“ Basic "+ EncodeBase64 (" nome utente: password "));}, succes: function (val) {// alert (val); alert (" Grazie per il tuo commento! ");}}); `
Patrioticcow,

69
beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); };funziona per me
Rico Suter, il

12
Problema ... Se le credenziali che passo falliscono, in Chrome viene quindi visualizzata una finestra di dialogo per inserire nuovamente username / pwd. Come posso impedire che questa seconda finestra di dialogo appaia se le credenziali falliscono?
David,

2
Questo non lascerà il nome utente e la password all'aperto affinché tutti possano vederli? Anche se è in base64 possono semplicemente decodificarlo. Lo stesso con la risposta qui sotto.
cbron,

6
@calebB L'autenticazione di base in generale lascia solo il nome utente e la password aperti a chiunque. Questo non è solo un problema con il metodo descritto qui. Se viene utilizzata l'autenticazione di base o realmente qualsiasi autenticazione, è necessario utilizzare anche SSL.
Jason Jackson,

354

Come cambiano le cose in un anno. Oltre all'attributo header al posto di xhr.setRequestHeader, l'attuale jQuery (1.7.2+) include un attributo username e password con la $.ajaxchiamata.

$.ajax
({
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  username: username,
  password: password,
  data: '{ "comment" }',
  success: function (){
    alert('Thanks for your comment!'); 
  }
});

MODIFICA da commenti e altre risposte: per essere chiari, al fine di inviare preventivamente l'autenticazione senza 401 Unauthorizedrisposta, anziché setRequestHeader(prima -1.7) utilizzare 'headers':

$.ajax
({
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  headers: {
    "Authorization": "Basic " + btoa(USERNAME + ":" + PASSWORD)
  },
  data: '{ "comment" }',
  success: function (){
    alert('Thanks for your comment!'); 
  }
});

15
Non dovrebbe essere usernamee non user? Inoltre non è esattamente lo stesso: dal docos online e dalla mia esperienza sembra che non sia preventivo come richiedono alcune API. In altre parole, invia l' Authorizationintestazione solo quando viene restituito un codice 401.
Stefano Fratini,

3
@StefanoFratini - hai ragione su entrambi i punti. Risolto il campo del nome utente, ed è bene sapere se l'autenticazione preventiva è la risposta solo alla sfida. L'impostazione dell'intestazione esplicitamente come in altre risposte consentirà l'uso di questa variante "passiva" dell'autent di base.
jmanning2k,

per me l'opzione di cui sopra non ha funzionato, questo ha funzionato come un fascino .. grazie
Anoop Isaac il

Vedi il commento sopra, correggi questa risposta per indicare {"Autorizzazione": "Base" + btoa ("user: pass")} come intestazione corretta
Jay

2
Questa è la risposta che stavo cercando! Il bit chiave in questa risposta per me è il modo in cui l'intestazione viene utilizzata per inviare preventivamente l'autenticazione. Alla mia domanda qui viene data una risposta. stackoverflow.com/questions/28404452/…
Steven Anderson,

63

Utilizzare il callback beforeSend per aggiungere un'intestazione HTTP con le informazioni di autenticazione in questo modo:

var username = $("input#username").val();
var password = $("input#password").val();  

function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = btoa(tok);
  return "Basic " + hash;
}
$.ajax
  ({
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '{}',
    beforeSend: function (xhr){ 
        xhr.setRequestHeader('Authorization', make_base_auth(username, password)); 
    },
    success: function (){
        alert('Thanks for your comment!'); 
    }
});

4
dovresti notare che "btoa" usato qui per la crittografia Base64 non è supportato nelle versioni IE inferiori a 10 e in alcune piattaforme mobili
SET

1
inoltre, secondo questo developer.mozilla.org/en-US/docs/DOM/window.btoa dovresti usare btoa (unescape (encodeURIComponent (str)))
SET

@SET, suppongo che debba essere btoa (encodeURIComponent (escape (str)))
Saurabh Kumar

Volevo ottenere la risposta, quindi mi sono liberato del falso asincrono e ho aggiunto il parametro del risultato alla funzione di successo. Avevo anche un'intestazione di autorizzazione pre-generata, quindi ho usato solo quella.
Radtek,

1
@SET è da notare che Base64 non è crittografia, è codifica. Se fosse una crittografia, non sarebbe semplicissimo decodificarla con una singola chiamata di funzione
Chris

40

Oppure usa semplicemente la proprietà headers introdotta in 1.5:

headers: {"Authorization": "Basic xxxx"}

Riferimento: API jQuery Ajax


Potresti dirmi come fare per ogni utente? Intendo ottenere il token API per ogni utente dal database e inviarlo con l'intestazione Ajax.
Haniye Shadman,

32

Gli esempi sopra sono un po 'confusi, e questo è probabilmente il modo migliore:

$.ajaxSetup({
  headers: {
    'Authorization': "Basic " + btoa(USERNAME + ":" + PASSWORD)
  }
});

Ho preso quanto sopra da una combinazione della risposta di Rico e Yossi.

La funzione btoa Base64 codifica una stringa.


5
Questa è una cattiva idea, perché invierai le informazioni di accesso con tutte le richieste AJAX, indipendentemente dall'URL. Inoltre, la documentazione per $.ajaxSetup()dice "Imposta valori predefiniti per future richieste Ajax. Il suo uso non è raccomandato. "
Zero3

27

Come altri hanno suggerito, è possibile impostare il nome utente e la password direttamente nella chiamata Ajax:

$.ajax({
  username: username,
  password: password,
  // ... other parameters.
});

O utilizza la proprietà headers se preferisci non memorizzare le tue credenziali in testo semplice:

$.ajax({
  headers: {"Authorization": "Basic xxxx"},
  // ... other parameters.
});

Qualunque sia il modo in cui lo invii, il server deve essere molto educato. Per Apache, il tuo file .htaccess dovrebbe assomigliare a questo:

<LimitExcept OPTIONS>
    AuthUserFile /path/to/.htpasswd
    AuthType Basic
    AuthName "Whatever"
    Require valid-user
</LimitExcept>

Header always set Access-Control-Allow-Headers Authorization
Header always set Access-Control-Allow-Credentials true

SetEnvIf Origin "^(.*?)$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is

Spiegazione:

Per alcune richieste tra domini, il browser invia una richiesta OPTIONS di verifica preliminare in cui mancano le intestazioni di autenticazione. Inserisci le direttive di autenticazione all'interno del tag LimitExcept per rispondere correttamente al preflight.

Quindi invia alcune intestazioni per dire al browser che è autorizzato ad autenticarsi e Access-Control-Allow-Origin per concedere l'autorizzazione per la richiesta tra siti.

In alcuni casi, il carattere jolly * non funziona come valore per Access-Control-Allow-Origin: è necessario restituire il dominio esatto del chiamante. Utilizzare SetEnvIf per acquisire questo valore.


5
Grazie per le informazioni che i browser inviano una richiesta di verifica preliminare CORS senza intestazioni di autenticazione! Dettagli come questo possono causare ore di debug!
jbandi,

23

Utilizzare la funzione jQuery ajaxSetup , che può impostare valori predefiniti per tutte le richieste ajax.

$.ajaxSetup({
  headers: {
    'Authorization': "Basic XXXXX"
  }
});

11

JSONP non funziona con l'autenticazione di base, quindi il callback jQuery beforeSend non funzionerà con JSONP / Script.

Sono riuscito a aggirare questa limitazione aggiungendo l'utente e la password alla richiesta (es. Utente: pw@domain.tld). Funziona praticamente con qualsiasi browser tranne Internet Explorer in cui l'autenticazione tramite URL non è supportata (la chiamata semplicemente non verrà eseguita).

Vedi http://support.microsoft.com/kb/834489 .


Immagino che per quanto riguarda la sicurezza sia una scelta sana non permettere questo
George Birbilis,

Il collegamento è interrotto (404).
Peter Mortensen,

10

Ci sono 3 modi per raggiungere questo obiettivo, come mostrato di seguito

Metodo 1:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
    headers: {
        "Authorization": "Basic " + btoa(uName+":"+passwrd);
    },
    success : function(data) {
      //Success block  
    },
   error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

Metodo 2:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
     beforeSend: function (xhr){ 
        xhr.setRequestHeader('Authorization', "Basic " + btoa(uName+":"+passwrd)); 
    },
    success : function(data) {
      //Success block 
   },
   error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

Metodo 3:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
    username:uName,
    password:passwrd, 
    success : function(data) {
    //Success block  
   },
    error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

8

Secondo la risposta di SharkAlley funziona anche con nginx.

Stavo cercando una soluzione per ottenere dati da jQuery da un server dietro nginx e limitato da Base Auth. Questo funziona per me:

server {
    server_name example.com;

    location / {
        if ($request_method = OPTIONS ) {
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, OPTIONS";
            add_header Access-Control-Allow-Headers "Authorization";

            # Not necessary
            #            add_header Access-Control-Allow-Credentials "true";
            #            add_header Content-Length 0;
            #            add_header Content-Type text/plain;

            return 200;
        }

        auth_basic "Restricted";
        auth_basic_user_file /var/.htpasswd;

        proxy_pass http://127.0.0.1:8100;
    }
}

E il codice JavaScript è:

var auth = btoa('username:password');
$.ajax({
    type: 'GET',
    url: 'http://example.com',
    headers: {
        "Authorization": "Basic " + auth
    },
    success : function(data) {
    },
});

Articolo che trovo utile:

  1. Le risposte di questo argomento
  2. http://enable-cors.org/server_nginx.html
  3. http://blog.rogeriopvl.com/archives/nginx-and-the-http-options-method/
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.