2

私は、gathercontent.com の API を使用して、ノード js で動作する単純な (!) ダイジェスト認証を取得しようとしています。

次のような「間違った資格情報」の応答が返されることを除いて、すべてが機能しているようです。

{ success: false, error: 'Wrong Credentials!' }

コードは次のようになります。

var https = require('https'),
    qs = require('querystring');
apikey = "[my api key goes in here]",
    pwd = "[my password goes in here]",
    crypto = require('crypto');


module.exports.apiCall = function () {

    var options = {
        host:'abcdefg.gathercontent.com',
        port:443,
        path:'/api/0.1/get_pages_by_project/get_me',
        method:'POST',
        headers:{
            "Accept":"application/json",
            "Content-Type":"application/x-www-form-urlencoded"
        }
    };

    var req = https.request(options, function (res) {

        res.on('data', function (d) {
            var creds = JSON.parse(d);


            var parsedDigest = parseDigest(res.headers['www-authenticate']);
            console.log(parsedDigest);
            var authopts = {
                host:'furthercreative.gathercontent.com',
                port:443,
                path:'/api/0.1/get_pages_by_project/get_me',
                method:'POST',
                headers:{
                    "Accept":"application/json",
                    "Content-Type":"application/x-www-form-urlencoded",
                    "Authorization" : getAuthHeader(parsedDigest, apikey, parsedDigest['Digest realm'], pwd)
                }
            };

            console.log(authopts);
            console.log('\n\n\n');
            var req2 = https.request(authopts, function (res2) {
                console.log("statusCode: ", res2.statusCode);
                console.log("headers: ", res2.headers);


                res2.on('data', function (d2) {
                    var result = JSON.parse(d2);

                });
            });

            req2.end();



        });

    });


    req.write('id=1234');

    req.end();

    req.on('error', function (e) {
        console.error(e);
    });

};

function parseDigest(s){

    var parts = s.split(',');
    var obj = {};
    var nvp = '';

    for(var i = 0; i < parts.length; i++){

        nvp = parts[i].split('=');
        obj[nvp[0]] = nvp[1].replace(/"/gi, '');
    }



    return obj;
}

function getAuthHeader(digest, apikey, realm, pwd){
    var md5 = crypto.createHash('md5');
    var s = '';

    var nc = '00000001';
    var cn = '0a4f113b';

    var HA1in = apikey+':'+realm+':'+pwd;
    md5 = crypto.createHash('md5');
    md5.update(HA1in);
    var HA1out = md5.digest('hex');

    var HA2in = 'POST:/api/0.1/get_pages_by_project/get_me';
    md5 = crypto.createHash('md5');
    md5.update(HA2in);
    var HA2out = md5.digest('hex');

    md5 = crypto.createHash('md5');
    var respIn = HA1out + ':' + digest.nonce + ':'+nc+':'+cn+':'+digest.qop+':'+ HA2out;
    md5.update(respIn);
    var resp = md5.digest('hex');


    s = [   'Digest username="',apikey,'", ',
        'realm="',digest['Digest realm'],'", ',
        'nonce="',digest.nonce,'", ',
        'uri="/api/0.1/get_pages_by_project/get_me", ',
        'cnonce="',cn,'", ',
        'nc="',nc,'", ',
        'qop="',digest.qop,'", ',
        'response="',resp,'", ',
        'opaque="',digest.opaque,'"'].join('')

    return s;
}

私はそれにカールしようと思いますが、方法がわかりません!

どんな助けでも大歓迎です!

4

5 に答える 5

5

あなたの問題に関連する可能性のある問題がいくつかあります。どれが実際の犯人であるかを判断するのは難しく、gathercontentの実装について何も知りません。'WWW-Authenticate'ヘッダーの例を貼り付けた場合、特定のヘルプを提供する方がはるかに簡単です。

だから私は実際の原因が何であるかを推測していますが、仕様に準拠するためにとにかく対処する必要があるいくつかの実際の問題があります(つまり、サーバーが少し異なることを開始するため、将来的に壊れないように保護します):

  • 作成しているAuthorizationヘッダーで、周囲の二重引用符を削除します。ncqop
  • qopcollectcontentが使用している値がわかりません。の場合auth-intは、ハッシュされたHTTPボディをに追加する必要があります。仕様の#3.2.2.3をHA2参照してください。さらに、qop値のコンマ区切りリストを指定している可能性があります。または、サーバーがの値をまったく送信しないでください。つまり、HTTPダイジェスト認証の最も基本的なfromを使用します。この場合、実装は仕様に違反することになります。たとえば、送信などは許可されません。qopcnoncenc
  • を介してレルムを取得しようとしますparsedDigest['Digest realm']。つまり、が最初のキーワードの後の最初の属性であると想定しています。realmDigestそうかもしれないし、そうでないかもしれませんが、それに頼るべきではありません(残りを分割する前parseDigestに文字列を取り除くように関数を変更してください)"Digest "
  • の使用方法では、ダイジェストは常にそのように大文字になり、、、などparsedDigestは常に小文字であると想定します。仕様によると、これらはすべて大文字と小文字を区別しませんrealmnonce

いくつかの無関係な問題:

  • サーバーは本当にあなたに使用を強制しますDigest authenticationか?これはHTTPSなので、そうすることもできます。HTTPSを使用するBasic authenticationと、同じように安全になります。(ここで自分自身に答えて、gathercontentをチェックした後:基本認証は明らかに不可能です)
  • あなたの質問に対する私のコメントで述べたように、cnonceすべてのリクエストに対してランダムである必要があります。特に、ウィキペディアからコピーして貼り付けないでください。これにより、脆弱性が高まります(ただし、すべてのデータがSSLを介して送信されるため、ここでは問題になりません。場合)

それをカールする方法について-これを試してください:

curl --data 'id=1234' --digest --user "apikey:pwd" https://abcdefg.gathercontent.com:443/api/0.1/get_pages_by_project/get_me
于 2012-10-18T00:59:19.290 に答える
1

このexpress-authモジュールは、HTTPダイジェストを含む複数の認証スキームをサポートしています。参照:https ://github.com/ciaranj/express-auth

もう1つの優れたオプションはpassport次のとおりです:https ://github.com/jaredhanson/passport

2つのモジュールのhttp-digestの例は、node.jsアプリケーションの認証を確立することと、認証要求をサードパーティに転送することに焦点を当てる傾向があります。ただし、少しのヌードリングで動作させることができるはずです。

押された場合、私はパスポートを使用します。提供されている例は、はるかに明確で文書化されています。

お役に立てば幸いです...

于 2012-10-14T16:32:27.083 に答える
0

mikeal のrequestモジュールを使用することをお勧めします。これにより、はるかに簡単でクリーンになります。

Request はまだ HTTP Auth をサポートしていませんが、残念ながら、Authorizationヘッダーを設定するだけで済みます。

于 2012-10-12T00:36:37.180 に答える