web-dev-qa-db-fra.com

Appels JQuery Ajax avec authentification HTTP de base

J'ai un serveur basé sur REST avec lequel j'essaie de communiquer avec JQuery. XML et JSON sont disponibles en tant que formats de réponse, donc j'utilise JSON.

Les connexions sont toutes SSL donc l'authentification HTTP de base a été notre méthode d'autorisation de choix, et nous n'avons eu aucun problème avec les autres frontaux (Javascript brut, Silverlight, etc ...)

Maintenant, j'essaye de mettre quelque chose ensemble avec JQuery et j'ai des problèmes sans fin en utilisant l'authentification HTTP de base.

J'ai parcouru de nombreuses questions précédentes, dont la plupart ont soit des solutions qui ne semblent pas vraiment fonctionner, soit blâmer tout le problème sur l'accès cross Origin, que j'ai déjà surmonté dans les tests Javascript de base. Les réponses fournissent toujours Access-Control-Allow-Origin Défini à l'en-tête Origin fourni dans la demande, et cela peut être vu dans les réponses de mes tests.

En javascript de base, cet appel complet se fait très simplement avec:

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

La tentative de JQuery est assez 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');
        }
    });

La seule méthode qui semble réellement fonctionner pour fournir l'authentification est l'insertion directe des données encodées Base64 dans la fonction beforeSend(). Si cela n'est pas inclus, il n'y a aucun progrès. Les propriétés de nom d'utilisateur et de mot de passe semblent être complètement ignorées.

Avec le comportement beforeSend() fourni, l'appel GET obtient une réponse positive avec les données incluses. Cependant, comme il s'agit d'un appel intersite, un appel OPTIONS est effectué avant l'appel GET et échoue toujours, car il n'utilise pas beforeSend() et obtient donc une réponse 401 en raison d'un échec d'authentification.

Existe-t-il une meilleure façon d'accomplir ce qui devrait être un appel très trivial? Le fait que la requête OPTIONS n'utilise pas la fonction beforeSend() doit-il être considéré comme un bug? Existe-t-il peut-être un moyen de désactiver complètement la vérification des OPTIONS? Il n'est pas possible de faire cet appel non intersite, car Javascript semble considérer même un numéro de port différent sur la même machine que "cross-site".

28
Dylan

Cette question est probablement bien après sa date d'expiration, mais je travaillais avec la même chose avec Jquery et suis tombé sur le même problème.

Les attributs de nom d'utilisateur et de mot de passe ne semblent pas effectuer un codage base64 du nom d'utilisateur/mot de passe comme vous le faites normalement pour effectuer l'authentification de base HTTP.

Examinez les requêtes suivantes (abrégées par souci de concision), en utilisant d'abord les paramètres "nom d'utilisateur" et "mot de passe" dans la méthode JQuery AJAX:

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

Et maintenant avec la méthode beforeSend:

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

Notez que la première méthode n'inclut pas d'en-tête "Autorisation" dans la demande, mais préfixe l'URL cible. Je ne suis pas un expert de l'authentification de base HTTP, mais cela indiquerait que la première n'est pas une implémentation appropriée et qu'elle échoue donc (ou du moins elle le fait avec ma propre implémentation de serveur).

Quant à votre demande OPTIONS en utilisant JSONP - vous pouvez éventuellement essayer d'utiliser ?callback=? dans votre URL au lieu d'utiliser l'option crossdomain, juste pour être explicite.

3
jmillar

Voici quelque chose qui agit comme une authentification unique pour les appels AJAX. Cela dépend de NTLM pour s'authentifier sur la page qui le javascript s'exécutera à partir de. Peut-être que cela vous aidera:

Code PHP:

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

En utilisant jQuery, vous l'utiliseriez de cette façon:

$.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
        },
});

Pour XMLHttpRequest standard:

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

Pour tous ceux qui rencontrent ce problème, j'ai résolu le problème d'interception des demandes OPTIONS avec Apache et de transfert uniquement des GET et POST au backend.

Cette solution est indépendante du serveur d'applications et fonctionne donc pour PHP et Java également:

<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>

Cordialement, Maurizio

1
Maurix