无法获取摘要身份验证以使用node.js

Lew*_*wis 2 authorization http node.js

我正在尝试使用来自gathercontent.com的API,使用节点js进行简单的(!)摘要式身份验证.

一切似乎都在工作,除了我仍然得到一个"错误的凭据"响应,看起来像这样:

{ success: false, error: 'Wrong Credentials!' }
Run Code Online (Sandbox Code Playgroud)

代码如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)

我会尝试和卷曲它,但我不知道如何!

任何帮助赞赏!

Eug*_*sky 5

我看到了一些可能与您的问题相关的问题.很难说哪些是真正的罪魁祸首,而不知道有关collectcontent的实现的任何信息.如果您粘贴了"WWW-Authenticate"标题的示例,则提供特定帮助会更容易.

所以我猜测实际原因是什么,但是这里有一些实际的问题,你应该解决,以符合规范(即保护它在未来不会破坏,因为服务器开始做的事情略有不同):

  • Authorization您创建头,去掉双引号周围nc,也许还qop
  • 我不知道qopgathercontent正在使用什么值.如果是auth-int,那么你还必须附加散列的HTTP主体HA2,参见规范的#3.2.2.3 - 此外,他们可能正在指定逗号分隔的qop值列表供您选择 - 或者服务器可能不是送价值qop可言,也就是说,它们用最基本的从HTTP的消化权威性,在您的实现将违反该规范,因为那你不准例如发送cnonce,nc等等.
  • 你试图获得领域parsedDigest['Digest realm'],即你假设它realm是初始Digest关键字后面的第一个属性.这可能是也可能不是这样,但你不应该依赖它(在拆分其余部分之前修改你的parseDigest函数来剥离字符串"Digest ")
  • 您使用的方式parsedDigest,你作出这样的假设摘要总是大写这样,那realm,nonce总是小写.根据规范,这些都是不区分大小写的

一些不相​​关的问题:

  • 服务器真的强迫你使用Digest authentication吗?这是HTTPS,所以您可以这样做Basic authentication,它更容易,并且使用HTTPS,同样安全.(在签出collectcontent之后在这里回答:基本的auth显然是不可能的)
  • 正如我对你的问题的评论中提到的,cnonce对于每个请求都应该是随机的,尤其是你不应该从维基百科中复制和粘贴它,这会使你更容易受到攻击(但这里不是问题,因为所有数据都在你的案件)

关于如何卷曲 - 试试这个:

curl --data 'id=1234' --digest --user "apikey:pwd" https://abcdefg.gathercontent.com:443/api/0.1/get_pages_by_project/get_me
Run Code Online (Sandbox Code Playgroud)