Comment envoyer un en-tête d'autorisation correct pour l'authentification de base

100

J'essaie de POST des données de mon API mais je ne peux pas passer l'authentification de base.

J'essaie:

$.ajax({
  type: 'POST',
  url: http://theappurl.com/api/v1/method/,
  data: {},
  crossDomain: true,
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Authorization', 'Basic [REDACTED]');
  }
});

La réponse de ma configuration de serveur est:

response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "POST"
response["Access-Control-Max-Age"] = "1000"
response["Access-Control-Allow-Headers"] = "*"

Les en-têtes que j'obtiens sont:

Demander des en-têtes

OPTIONS /api/v1/token-auth/ HTTP/1.1
Host: theappurl.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31
Access-Control-Request-Headers: origin, authorization, content-type
Accept: */*
Referer: http://127.0.0.1:8080/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: es,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

En-tête de réponse

HTTP/1.1 401 Unauthorized
Server: nginx/1.1.19
Date: Fri, 16 Aug 2013 01:29:21 GMT
Content-Type: text/html
Content-Length: 597
Connection: keep-alive
WWW-Authenticate: Basic realm="Restricted"

Je suppose que la configuration du serveur est bonne car je peux accéder à l'API à partir du client REST avancé (extension Chrome)

Aucune suggestion?

PD: L'en-tête que j'obtiens du client REST avancé est:

    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31
    Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
    Authorization: Basic [REDACTED]
    Content-Type: application/x-www-form-urlencoded 
    Accept: */*
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: es,en;q=0.8
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

et

    Server: nginx/1.1.19 
    Date: Fri, 16 Aug 2013 01:07:18 GMT 
    Content-Type: application/json; charset=utf-8 
    Transfer-Encoding: chunked 
    Connection: keep-alive
    Vary: Accept, Cookie 
    Allow: POST, OPTIONS 
    X-Robots-Tag: noindex

envoi méthode OPTION

individuo7
la source
19
Je me rends compte que cet article est mort depuis longtemps, mais je tiens simplement à le signaler au cas où vous ne seriez pas conscient qu'en publiant votre en-tête Authorization:, vous avez essentiellement publié votre mot de passe en clair. La chaîne de charabia il y a juste l'encodage base64 de votre nom d'utilisateur: mot de passe, donc tout le monde peut voir votre mot de passe. J'espère que vous vous en êtes rendu compte et que vous avez utilisé un mot de passe factice ici :)
Lexelby
Cela fonctionne très bien avec le serveur de rapports ssrs 2017. Il cache le mot de passe et le nom d'utilisateur dans l'URL.
Clark Vera
@Lexelby: Le nom d'utilisateur est "l'utilisateur" et le mot de passe est "et le mot de passe" en espagnol. Donc je suppose que ce ne sont pas de véritables références.
pdr

Réponses:

48

Vous pouvez inclure l'utilisateur et le mot de passe dans l'URL:

http://user:[email protected]/index.html

voir cette URL, pour en savoir plus

Informations d'identification d'authentification de base HTTP transmises dans l'URL et le chiffrement

bien sûr, vous aurez besoin du mot de passe du nom d'utilisateur, ce n'est pas le cas 'Basic hashstring.

J'espère que cela t'aides...

Dru
la source
6
Cette solution ne fonctionnera pas pour le navigateur natif d'Android (Pre KitKat). Le formulaire de nom d'utilisateur / de connexion apparaîtra toujours pour votre utilisateur, alors soyez prudent.
Sterling Bourne
58
Cette méthode expose le nom d'utilisateur et le mot de passe à toute personne écoutant sur le réseau ou les appareils ...
Adam
5
La chaîne de hachage @Adam n'est pas non plus sûre
Mustafa
38
Cela ne répond pas du tout à la question. Le transmettre comme une URL n'est pas un en-tête.
jemiloii
5
raison du vote négatif: developer.mozilla.org/en-US/docs/Web/HTTP/Authentication . Vers la fin de l'article, il mentionne queThe use of these URLs is deprecated
anurupr
70

Par https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding et http://en.wikipedia.org/wiki/Basic_access_authentication , voici comment faire l'authentification de base avec un en-tête à la place de mettre le nom d'utilisateur et le mot de passe dans l'URL. Notez que cela ne masque toujours pas le nom d'utilisateur ou le mot de passe de toute personne ayant accès au réseau ou à ce code JS (par exemple, un utilisateur qui l'exécute dans un navigateur):

$.ajax({
  type: 'POST',
  url: http://theappurl.com/api/v1/method/,
  data: {},
  crossDomain: true,
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(unescape(encodeURIComponent(YOUR_USERNAME + ':' + YOUR_PASSWORD))))
  }
});
seanp2k
la source
1
Remarque: Un polyfill window.btoa tel que Base64.js sera nécessaire pour que cette fonctionnalité fonctionne dans IE6,7,8,9. Unescape est également obsolète selon ECMAScript v3.
null
@Techbrunch vous vous trompez, l'exemple de seanp2k fonctionne très bien, il utilise une astuce très connue pour décoder les caractères Unicode en ASCII, il utilise en fait le fait que (un) escape ne prend pas en charge Unicode, mais (dec) encodeURIComponent le fait ..
40

Réponse de NodeJS:

Au cas où vous voudriez le faire avec NodeJS: créez un point de terminaison GET to JSON avec en- Authorizationtête et récupérez un Promiseretour:

Première

npm install --save request request-promise

( voir sur npm ) puis dans votre .jsdossier:

var requestPromise = require('request-promise');

var user = 'user';
var password = 'password';

var base64encodedData = new Buffer(user + ':' + password).toString('base64');

requestPromise.get({
  uri: 'https://example.org/whatever',
  headers: {
    'Authorization': 'Basic ' + base64encodedData
  },
  json: true
})
.then(function ok(jsonData) {
  console.dir(jsonData);
})
.catch(function fail(error) {
  // handle error
});
jakub.g
la source
1
Merci, vous avez sauvé ma journée :)
Sparw
Merci cela a fonctionné dans mon application de réaction qui a utilisé "fetch"
MohsenFM
13

Si vous êtes dans un environnement de navigateur, vous pouvez également utiliser btoa .

btoaest une fonction qui prend une chaîne comme argument et produit une chaîne ASCII encodée en Base64. Son supporté par 97% des navigateurs .

Exemple:

> "Basic " + btoa("billy"+":"+"secretpassword")
< "Basic YmlsbHk6c2VjcmV0cGFzc3dvcmQ="

Vous pouvez ensuite ajouter Basic YmlsbHk6c2VjcmV0cGFzc3dvcmQ=à l'en- authorizationtête.

Notez que les mises en garde habituelles concernant l'authentification HTTP BASIC s'appliquent, surtout si vous n'envoyez pas votre trafic via https, une écoute clandestine peut simplement décoder la chaîne encodée en Base64 et obtenir ainsi votre mot de passe.

Cette réponse security.stackexchange.com donne un bon aperçu de certains des inconvénients.

Fernandohur
la source
3

pas besoin d'utiliser l'utilisateur et le mot de passe dans le cadre de l'URL

tu peux essayer ça

byte[] encodedBytes = Base64.encodeBase64("user:passwd".getBytes());

String USER_PASS = new String(encodedBytes);

HttpUriRequest request = RequestBuilder.get(url).addHeader("Authorization", USER_PASS).build();
Erhanck
la source