28

Mam serwer oparty na REST, który próbuję komunikować się przy użyciu JQuery. Zarówno XML, jak i JSON są dostępne jako formaty odpowiedzi, więc używam JSON.Połączenia Ajax z JQuery z podstawowym uwierzytelnianiem HTTP

Połączenia SSL są tak podstawowego uwierzytelniania HTTP była nasza metoda autoryzacji z wyboru, a nie mieliśmy żadnych problemów z innymi przednimi końcami (surowe JavaScript, Silverlight, etc ...)

Teraz jestem próby umieścić coś razem z JQuery i mieć niekończące się problemy przy użyciu podstawowego uwierzytelniania HTTP.

Przeszukałem wiele wcześniejszych pytań, z których większość ma rozwiązania, które nie działają, ani nie obwiniają całego problemu związanego z dostępem krzyżowym, co już pokonałem w podstawowych testach JavaScript. Odpowiedzi zawsze dostarczają Access-Control-Allow-Origin ustawionego nagłówka Origin w żądaniu, co można zobaczyć w odpowiedziach z moich testów.

W podstawowej javascript, cała ta rozmowa jest bardzo łatwo osiągnąć z:

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

jQuery próba ta jest dość standardowe:

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

Jedyną metodą, która faktycznie wydaje się działać, aby zapewnić uwierzytelnianie to bezpośrednie wstawienie zakodowanych danych Base64 w funkcji beforeSend(). Jeśli nie jest to uwzględnione, nie ma żadnych postępów. Nazwa użytkownika i hasło wydają się być całkowicie ignorowane.

Zgodnie z podanym warunkiem beforeSend(), wywołanie GET uzyskuje pozytywną odpowiedź z dołączonymi danymi. Ponieważ jednak jest to połączenie między lokacjami, wywołanie OPTIONS jest wykonywane przed wywołaniem GET i zawsze kończy się niepowodzeniem, ponieważ nie korzysta z beforeSend() i dlatego otrzymuje odpowiedź 401 z powodu nieudanego uwierzytelnienia.

Czy istnieje lepszy sposób osiągnięcia tego, co powinno być bardzo banalnym wywołaniem? Czy fakt, że żądanie OPTIONS nie korzysta z przetwarzania funkcji beforeSend(), należy uznać za błąd? Czy jest być może sposób, aby całkowicie wyłączyć kontrolę OPTIONS? Nie można tego połączenia przekierować na drugą stronę, ponieważ JavaScript wydaje się uwzględniać nawet inny numer portu na tym samym komputerze co "cross-site".

+0

Nie musisz mieć nazwę użytkownika/hasło pól przed wysyłać i . Chciałbym usunąć pola nazwa użytkownika/hasło z twojej funkcji $ .ajax. –

Odpowiedz

1

Oto coś, co działa jako uwierzytelnianie tranzytowe dla wywołań AJAX. Jest to zależne od NTLM w celu uwierzytelnienia na stronie, z której będzie wykonywany skrypt javascript. Może to pomoże: Kod

PHP:

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

jQuery byłoby użyć to w ten sposób:

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

Dla standardowego XMLHttpRequest:

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

Byłoby pomocne, gdybyś podał przykład tego, jak powinna wyglądać zmienna "auth". Wyobrażam sobie, że jest to obiekt z właściwościami użytkownika i hasła, ale najlepiej byłoby powiedzieć jednoznacznie o tym – TKoL

+0

@TKoL OP podaje przykład wartości 'auth'. Zasadniczo jest to: '" Basic "+ encodeBase64 (nazwa użytkownika +": "+ hasło));' –

+0

thanks @ wes.hysell. Dla mnie to nie było oczywiste. – TKoL

3

To pytanie jest prawdopodobnie znacznie wcześniej niż jego data wygaśnięcia, ale pracowałem z tym samym z Jquery i natknąłem się na s ame problem.

Atrybuty nazwy użytkownika i hasła nie wydają się kodować base64 nazwy użytkownika/hasła, tak jak w przypadku zwykłego uwierzytelniania podstawowego HTTP.

spojrzeć na następujące wnioski (skrócona dla zwięzłość), najpierw przy użyciu „login” i „hasło” parametry metody jQuery AJAX:

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

a teraz metodą beforeSend:

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

Należy zauważyć, że pierwsza metoda nie zawiera nagłówka "Autoryzacja" w żądaniu, ale zamiast tego dodaje prefiks docelowy adres URL. Nie jestem ekspertem od podstawowego uwierzytelniania HTTP, ale wskazywałoby to, że ten pierwszy nie jest prawidłową implementacją i dlatego się nie powiedzie (lub przynajmniej nie we własnej implementacji serwera).

Jeśli chodzi o żądania OPCJONALNOŚCI za pomocą JSONP - możesz spróbować użyć adresu ?callback=? w adresie URL, zamiast korzystać z opcji crossdomain, aby uzyskać wyraźne informacje.

1

Dla każdego, kto zgłosił ten problem, udało mi się rozwiązać problem przechwytujący żądania OPTIONS za pomocą Apache'a i przekazujący tylko GET i POST do backendu.

To rozwiązanie jest appserver niezależny i działa w ten sposób dla PHP i Java, a także:

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

Pozdrowienia, Maurizio

+0

Dla prawidłowej implementacji REST prawdopodobnie będziesz chciał dołączyć również metodę "PUT". –

+0

z pewnością, dzięki Jezen! – Maurix

Powiązane problemy