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

Http 无法获取摘要身份验证以使用node.js,http,node.js,authorization,Http,Node.js,Authorization,我正在尝试使用gathercontent.com上的API与node js进行简单的(!)摘要身份验证 一切似乎都正常,但我仍然收到如下“错误凭据”响应: { success: false, error: 'Wrong Credentials!' } var https = require('https'), qs = require('querystring'); apikey = "[my api key goes in here]", pwd = "[my passwor

我正在尝试使用gathercontent.com上的API与node 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;
}
代码如下所示:

{ 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;
}
var https=require('https'),
qs=要求(“查询字符串”);
apikey=“[my api key进入此处]”,
pwd=“[我的密码在这里]”,
加密=需要(“加密”);
module.exports.apiCall=函数(){
变量选项={
主持人:“abcdefg.gathercontent.com”,
港口:443,
路径:'/api/0.1/get_pages_by_project/get_me',
方法:'POST',
标题:{
“接受”:“应用程序/json”,
“内容类型”:“应用程序/x-www-form-urlencoded”
}
};
var req=https.request(选项、函数(res){
res.on('数据',功能(d){
var creds=JSON.parse(d);
var parsedDigest=parseDigest(res.headers['www-authenticate']);
console.log(parsedDigest);
var authopts={
主持人:'FutureCreative.gathercontent.com',
港口:443,
路径:'/api/0.1/get_pages_by_project/get_me',
方法:'POST',
标题:{
“接受”:“应用程序/json”,
“内容类型”:“应用程序/x-www-form-urlencoded”,
“授权”:getAuthHeader(parsedDigest,apikey,parsedDigest['Digest realm',],pwd)
}
};
console.log(authopts);
console.log('\n\n\n');
var req2=https.request(authopts,函数(res2){
console.log(“状态代码:”,res2.statusCode);
log(“headers:”,res2.headers);
res2.on('data',函数(d2){
var result=JSON.parse(d2);
});
});
请求2.结束();
});
});
请求写入('id=1234');
请求结束();
请求开启('错误',功能(e){
控制台错误(e);
});
};
函数摘要{
var parts=s.split(',');
var obj={};
var nvp='';
对于(变量i=0;i
我想试着卷曲,但我不知道怎么做


非常感谢您的帮助!

我建议您使用mikeal的模块,这将使它更简单、更干净


请求尚未支持HTTP身份验证,遗憾的是,您只需设置
授权
头。

快速身份验证
模块支持多种身份验证方案,包括HTTP摘要。请参阅:

另一个很好的选择是
passport
at:

这两个模块中的http摘要示例倾向于为node.js应用程序建立身份验证,而不是将身份验证请求转发给第三方。不过,您应该能够通过一点欺骗使其正常工作

如果被追问,我会使用passport。提供的例子更清楚,更有文档记录


希望这对您有所帮助……

我发现了一些可能与您的问题有关的问题。由于不了解gathercontent的实现,很难判断哪些问题是真正的罪魁祸首。如果您粘贴了他们的“WWW Authenticate”头的示例,则提供具体帮助会容易得多

因此,我推测实际原因是什么,但这里有一些实际问题,您无论如何都应该解决,以符合规范(即,由于服务器开始做的事情略有不同,因此保护它在将来不会崩溃):

  • 在您正在创建的
    Authorization
    标题中,删除
    nc
    周围的双引号,也可以删除
    qop
  • 我不知道
    qop
    value gathercontent在使用什么。如果它是
    auth int
    ,那么您还必须将散列的HTTP正文附加到
    HA2
    ,请参见-此外,他们可能指定一个以逗号分隔的qop值列表供您选择-或者服务器可能无法识别d表示
    qop
    的值,即它们使用最基本的HTTP摘要身份验证from,其中您的实现将违反,因为这样您就不允许发送
    cnence
    nc
  • 您试图通过
    parsedDigest['Digest realm']
    获取领域,即您假设
    领域
    是初始
    Digest
    关键字之后的第一个属性。可能是这样,也可能不是这样,但您不应该依赖它(修改
    parseDigest
    函数,在拆分其余字符串之前,先剥离字符串
    “Digest”
  • 您使用parsedDigest的方式是