node.js - 在 Node.js 中使用 http.client 进行摘要认证的问题

标签 node.js digest-authentication

我尝试在使用 http.get 时实现摘要请求,每次都收到“摘要身份验证失败”消息:(

var hashlib = require('hashlib'),
    http = require('http'),
    url = require('url'),
    qs = require('querystring'),
    hashlib = require('hashlib');


var username = 'user';
var password = 'pass';

var options = {
    'host' : 'username.livejournal.com',
    'path' : '/data/rss?auth=digest'
};

http.get(options, function(res) {
    res.setEncoding('utf-8');

    // got 401, okay
    res.on('data', function(chunk) {

        var authResponseParams = qs.parse(res.headers['www-authenticate'].substr(7), ', '); // cut "Digest "

        var ha1 = hashlib.md5(username + ':' + authResponseParams.realm + ':' + password);
        var ha2 = hashlib.md5('GET:' + options.path);
        var response = hashlib.md5(ha1 + ':' + authResponseParams.nonce + ':1::auth:' + ha2);

        var authRequestParams = {
            'username' : username,
            'realm' : authResponseParams.realm,
            'nonce' : authResponseParams.nonce,
            'uri' : options.path,
            'qop' : authResponseParams.qop,
            'nc' : '1',
            'cnonce' : '',
            'response' : response
        };

        options.headers = {
            'Authorization' : 'Digest ' + qs.stringify(authRequestParams, ',')
        };

        http.get(options, function(res) {
            res.setEncoding('utf-8');

            res.on('data', function(chunk) {
                console.log(chunk);
            });
        });
    });
}).on('error', function(e) {
    console.log('Got error: ' + e.message);
});

这段代码有什么问题?

最佳答案

一些事情:

  • 不一定会调用 res.on('data', fn) 中的回调,因为响应不一定包含正文,仅包含 header 。所以请改用 res.on('end', fn)
  • 解析 Digest header 会产生一个非常奇特的对象,因为参数可以被引用并且可以包含空格(被转义)。
  • 编写身份验证 header 的方式相同。

这是一个适合我的版本:

var hashlib = require('hashlib'),
    http = require('http'),
    _ = require('underscore')

var username = 'user';
var password = 'pwd';

var options = {
  'host' : 'host',
  'path' : '/path'
};

http.get(options, function(res) {
    res.setEncoding('utf-8');
    res.on('end', function() {
        var challengeParams = parseDigest(res.headers['www-authenticate'])
        var ha1 = hashlib.md5(username + ':' + challengeParams.realm + ':' + password)
        var ha2 = hashlib.md5('GET:' + options.path)
        var response = hashlib.md5(ha1 + ':' + challengeParams.nonce + ':1::auth:' + ha2)
        var authRequestParams = {
          username : username,
          realm : challengeParams.realm,
          nonce : challengeParams.nonce,
          uri : options.path, 
          qop : challengeParams.qop,
          response : response,
          nc : '1',
          cnonce : '',
        }
        options.headers = { 'Authorization' : renderDigest(authRequestParams) }
        http.get(options, function(res) {
          res.setEncoding('utf-8')
          var content = ''
          res.on('data', function(chunk) {
            content += chunk
          }).on('end', function() {
            console.log(content)
          })
        });
    });
})

function parseDigest(header) {  
  return _(header.substring(7).split(/,\s+/)).reduce(function(obj, s) {
    var parts = s.split('=')
    obj[parts[0]] = parts[1].replace(/"/g, '')
    return obj
  }, {})  
}
function renderDigest(params) {
  var s = _(_.keys(params)).reduce(function(s1, ii) {
    return s1 + ', ' + ii + '="' + params[ii] + '"'
  }, '')
  return 'Digest ' + s.substring(2);
}

关于node.js - 在 Node.js 中使用 http.client 进行摘要认证的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7516036/

相关文章:

javascript - nodejs循环async.parallel回调

tomcat - 如何使用 auth DIGEST 控制 Tomcat 中的 session 过期

digest-authentication - 什么是摘要认证?

node.js - 如何转义字符串但不影响nodejs mysql js中的LIKE结果

mysql - 将数据从 SQL 导入到 MongoDB。全有或全无

node.js - S3.putObject - 回调永远不会被调用

java - 如何在 Java(或 C#)中使用摘要身份验证 HTTP 通过 HTTP 发送 SOAP 请求?

node.js - Sequelize.sync() 期间的 ETIMEDOUT

android - 需要帮助为 Android 创建摘要式身份验证

delphi - Delphi XE 中使用 Indy IdHttp Digest 身份验证的 401