web-dev-qa-db-fra.com

Comment faire XMLHttpRequest cross-domaine avec Credentials, HTTP Authorization (CORS)?

Je ne peux pas faire de demande interdomaine avec un en-tête d'autorisation (test avec Firefox). J'ai des demandes qui fonctionnent sans authentification, mais une fois que j'ai défini withCredentials sur true, je ne peux plus lire la réponse du serveur.

Sur le serveur, je renvoie ces en-têtes (en utilisant un after_request méthode dans Flask):

resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers['Access-Control-Allow-Credentials'] = 'true'
resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
resp.headers['Access-Control-Allow-Headers'] = 'Authorization'

Aucun appel OPTIONS n'est réellement effectué par Firefox. Sur le client, je lance un appel XMLHttpRequest:

var xhr = new XMLHttpRequest()
xhr.open( 'POST', 'http://test.local:8002/test/upload', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
    console.log( xhr.status, xhr.statusText )
}
xhr.send(fd)

Sans withCredentials set, l'instruction log enregistrera les informations attendues sur la console. Une fois que j'ai défini la valeur, la xhr ne permet pas l'accès et j'écris simplement une valeur 0 et une chaîne vide. Je n'ai pas défini l'en-tête d'autorisation ici, mais cela ne devrait pas affecter ma capacité à lire le résultat.

Si j'essaye d'ajouter un nom d'utilisateur/mot de passe à la commande "open", j'obtiens un NS_ERROR_DOM_BAD_URI: Access to restricted URI denied Erreur.

Qu'est-ce que je fais mal?

23
edA-qa mort-ora-y

J'ai écrit un article avec une configuration CORS complète.

J'ai trouvé plusieurs problèmes pouvant entraîner ce problème:

  1. Le Access-Control-Allow-Origin Ne peut pas être un caractère générique si des informations d'identification sont utilisées. Il est plus simple de copier l'en-tête Origin de la demande dans ce champ. On ne sait pas vraiment pourquoi la norme interdirait un caractère générique.
  2. Firefox met en cache les résultats du contrôle d'accès même si vous videz le cache (peut-être pour la session). Le redémarrage l'a forcé à faire une nouvelle demande OPTIONS. Pour aider au débogage, j'ai ajouté l'en-tête Access-Control-Max-Age: 1
  3. Le nom d'utilisateur/mot de passe de la commande open n'est apparemment pas utilisable comme identifiant. Vous devez ajouter vous-même un en-tête Authorization. xhr.setRequestHeader( 'Authorization', 'Basic ' + btoa( user + ':' + pass ) )

Dans l'ensemble, le système withCredentials est plutôt braindead. Il est plus facile d'écrire simplement un serveur qui accepte l'autorisation dans le corps de la demande.

42
edA-qa mort-ora-y