http - 无法获得摘要身份验证以使用 node.js

标签 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 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;
}

我会尝试 Curl 到它,但我不确定该怎么做!

感谢任何帮助!

最佳答案

我发现有几个问题可能与您的问题有关。很难说出哪些是真正的罪魁祸首,因为对 gathercontent 的实现一无所知。如果您粘贴了他们的“WWW-Authenticate” header 的示例,那么提供具体帮助会容易得多。

所以我推测实际原因是什么,但这里有一些您无论如何都应该解决的实际问题,以符合规范(即防止它在将来因为服务器开始做事略有不同而中断):

  • Authorization在您创建的 header 中,删除双引号 nc ,也许还有 qop
  • 我不知道是什么qop值 gathercontent 正在使用。如果是 auth-int ,那么您还必须将散列的 HTTP 正文附加到 HA2 , 请参阅 #3.2.2.3 of the spec - 此外,他们可能会指定逗号分隔的 qop 值列表供您选择 - 或者服务器可能不会发送 qop 的值|完全,即他们使用最基本的 HTTP 摘要身份验证,其中您的实现将违反 spec ,因为那时你不被允许,例如发送 cnonce , nc
  • 你尝试通过parsedDigest['Digest realm'] 获取领域,即 您假设 realm是初始 Digest 之后的第一个属性 关键字。这可能是也可能不是这种情况,但您不应该依赖它(修改您的 parseDigest 函数以在拆分其余部分之前剥离字符串 "Digest ")
  • 你使用的方式parsedDigest ,您假设 Digest 始终以这种方式大写,并且 realm , nonce 总是小写。根据规范,这些都是不区分大小写

几个不相关的问题:

  • 服务器真的强制你使用Digest authentication吗? ?这是 HTTPS,所以你不妨做 Basic authentication ,它更容易,并且使用 HTTPS,同样安全。 (在查看 gathercontent 后在这里回答自己:基本身份验证显然是 not possible )
  • 正如我在对您的问题的评论中提到的,cnonce每个请求应该是随机的,特别是,你不应该从 Wikipedia 复制和粘贴它,这让你更容易受到攻击(但这里不是问题,因为在你的情况下所有数据都通过 SSL)

关于如何 curl 它 - 试试这个:

curl --data 'id=1234' --digest --user "apikey:pwd" https://abcdefg.gathercontent.com:443/api/0.1/get_pages_by_project/get_me

关于http - 无法获得摘要身份验证以使用 node.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12850646/

相关文章:

android - Android 4 或更高版本上的 HTTP 连接出错?

c# - 在 C# 应用程序中创建 HTTP post 请求并接收响应并解析响应

mysql - 在 sequelize 中向现有表添加新列

javascript - "."没有被解析为 require() Node.js 的一部分

graphql - 如何测试 Hasura 授权?

javascript - 保持连接活跃

Django - 减少 URL 查询字符串的长度

javascript - 在 3 模式上填充 mongoose

Perl SOAP::LITE——无法验证?

asp.net-mvc - 具有自定义重定向的 AuthorizeAttribute