我尝试在使用 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/