web-dev-qa-db-ja.com

HTTP基本認証を使用したJQuery Ajax呼び出し

RESTベースのサーバーで、JQueryを使用して通信しようとしています。XMLとJSONの両方が応答形式として使用できるため、JSONを使用しています。

接続はすべてSSLであるため、HTTP基本認証が選択の承認方法であり、他のフロントエンド(生のJavascript、Silverlightなど)で問題はありませんでした。

今、私はJQueryと何かを組み合わせようとし、HTTP基本認証を使用して無限の問題を抱えています。

私は以前の多くの質問を精査しましたが、そのほとんどは実際には機能しないと思われる解決策を持っているか、Origin間のアクセスに関する問題全体を非難しています。応答は常に、リクエストで指定されたOriginヘッダーに設定された_Access-Control-Allow-Origin_を提供します。これは、テストの応答で確認できます。

基本的なJavaScriptでは、この呼び出し全体は次のようにして非常に簡単に実行されます。

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

これに対するJQueryの試みはかなり標準的なものです。

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

認証を提供するために実際に機能すると思われる唯一の方法は、beforeSend()関数へのBase64エンコードデータの直接挿入です。これが含まれていない場合、何の進展もありません。ユーザー名とパスワードのプロパティは完全に無視されるようです。

beforeSend()動作が提供されると、GET呼び出しはデータが含まれた肯定応答を取得します。ただし、これはクロスサイトコールであるため、OPTIONSコールはGETコールの前に実行され、常に失敗します。これは、beforeSend()を使用しないため、認証の失敗により401応答を取得するためです。

非常に些細な呼び出しであるべきことを達成するためのより良い方法はありますか? OPTIONSリクエストがbeforeSend()関数処理を利用しないという事実はバグと見なされるべきですか? OPTIONSチェックを完全に無効にする方法はありますか? Javascriptは、同じマシン上の異なるポート番号でさえ「クロスサイト」と見なしているため、クロスサイトではなくこの呼び出しを行うことはできません。

28
Dylan

この質問はおそらくその有効期限をかなり過ぎていますが、私はJqueryで同じことをやっていて、同じ問題に遭遇しました。

ユーザー名とパスワードの属性は、通常HTTP基本認証を実行する場合のように、ユーザー名/パスワードのbase64エンコードを実行しないようです。

最初にJQuery AJAXメソッドで "username"および "password"パラメータを使用して、次のリクエスト(簡潔にするために短縮されています)を確認します。

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

そして今、beforeSendメソッドで:

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

最初の方法では、リクエストに「Authorization」ヘッダーが含まれず、代わりにターゲットURLのプレフィックスが付加されることに注意してください。私はHTTP基本認証の専門家ではありませんが、前者は適切な実装ではないため、失敗します(少なくとも、独自のサーバー実装では失敗します)。

JSONPを使用したOPTIONSリクエストについては、明示的にcrossdomainオプションを使用する代わりに、URLで?callback=?を使用してみてください。

3
jmillar

以下は、AJAX呼び出しのパススルー認証として機能するものです。これは [〜#〜] ntlm [〜#〜] に依存し、 javascriptが実行されます。たぶんこれはあなたを助けるでしょう:

PHPコード:

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

JQueryを使用すると、次のように使用できます。

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

標準のXMLHttpRequestの場合:

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

この問題を解決するために、ApacheでOPTIONSリクエストをインターセプトし、GETとPOSTのみをバックエンドに転送する問題を解決しました。

このソリューションはアプリサーバーに依存しないため、PHPおよび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/$1 [L,P]

</VirtualHost>

よろしく、マウリツィオ

1
Maurix