JQuery appels Ajax avec authentification HTTP Basic

j'ai un serveur basé sur le repos avec lequel j'essaie de communiquer en utilisant JQuery. XML et JSON sont disponibles sous forme de 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 front ends (JavaScript brut, Silverlight, etc...)

maintenant je tente de mettre quelque chose en place avec JQuery et avoir des problèmes sans fin en utilisant HTTP Basic Authentication.

j'ai passé en revue de nombreuses questions précédentes dont la plupart ont des solutions qui ne semblent pas fonctionner réellement ou blâmer l'ensemble du problème sur l'accès d'origine croisée, que j'ai déjà surmonté dans le test de base de Javascript. Les réponses fournissent toujours Access-Control-Allow-Origin défini à l'en-tête D'origine fourni dans la requête, et cela peut être vu dans les réponses de mes tests.

en basic javascript, cet appel entier est tout simplement accompli avec:

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

JQuery tentative à cet égard 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 fonctionner pour fournir l'authentification est l'insertion directe des données encodées en Base64 dans le beforeSend() fonction. Si cela n'est pas inclus, il n'y a aucun progrès. Les propriétés Nom d'utilisateur et mot de passe semblent être complètement ignorées.

beforeSend() comportement fournis, les OBTENIR de l'appel reçoit une réponse positive avec les données incluses. Cependant, comme il s'agit d'un appel cross site, un appel OPTIONS est exécuté avant L'appel GET et échoue toujours, car il ne fait pas usage de beforeSend() et obtient donc une réponse 401 en raison d'une authentification ratée.

Est-il une meilleure façon d'accomplir ce qui doit être triviale appel? Si le fait que la requête OPTIONS n'utilise pas beforeSend() le traitement de la fonction doit-il être considéré comme un bogue? Y a-t-il peut-être un moyen de désactiver entièrement la vérification des OPTIONS? Il n'est pas possible de rendre cet appel non cross-site, car Javascript semble considérer même un numéro de port différent sur la même machine que "cross-site".

28
demandé sur Kirby 2012-03-14 00:59:40

3 réponses

cette question est probablement bien au-delà de sa date d'expiration, mais je travaillais avec la même chose avec Jquery et je suis tombé sur le même problème.

les attributs username et password ne semblent pas faire un encodage base64 du nom d'utilisateur/mot de passe comme vous le faites normalement pour accomplir HTTP basic auth.

regardez les requêtes suivantes (raccourcies par souci de brièveté), en utilisant d'abord les paramètres" Nom d'utilisateur "et" mot de passe " dans la méthode AJAX de JQuery:

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 'Authorization' dans la requête, mais préfixe plutôt L'URL cible. Je ne suis pas un expert en authentification HTTP de base, mais cela indiquerait que la première n'est pas une implémentation correcte et qu'elle échoue donc (ou du moins qu'elle échoue avec ma propre implémentation de serveur).

quant à votre requête D'OPTIONS en utilisant JSONP - vous pouvez éventuellement essayer d'utiliser ?callback=? dans votre URL au lieu d'utiliser le crossdomain option, juste pour être explicite.

3
répondu jmillar 2012-11-27 12:45:28

voici quelque chose qui agit comme une authentification de passage pour les appels AJAX. Cela repose sur NTLM pour s'authentifier sur la page que le javascript s'exécute dans. Peut-être que cela peut vous aider:

PHP Code:

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

en utilisant jQuery vous l'utilisez 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
        },
});

For standard XMLHttpRequest:

var xml = new XMLHttpRequest();
xml.open('GET', './somePage.php', true);
xml.setRequestHeader('Authorization', auth); // <<<<----- USED HERE
xml.send();
1
répondu wes.hysell 2012-06-27 16:20:46

pour tous ceux qui viennent à travers ce problème, j'ai résolu le problème intercepting OPTIONS requests avec Apache et redirigeant seulement Les GETs et les messages vers le backend.

cette solution est indépendante de l'appserveur et fonctionne donc aussi bien pour PHP que pour Java:

<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/ [L,P]

</VirtualHost>

ce qui Concerne, Maurizio

1
répondu Maurix 2015-07-24 22:59:56