我正在尝试使用gathercontent.com中的API来使用节点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;
}
我会尝试和卷曲,但我不确定如何!
任何帮助表示赞赏!
答案 0 :(得分:5)
我发现了一些与您的问题有关的问题。很难说哪些是真正的罪魁祸首,而不知道有关collectcontent的实现的任何信息。如果您粘贴了“WWW-Authenticate”标题的示例,则提供特定帮助会更容易。
所以我猜测实际原因是什么,但是这里有一些实际问题,你应该解决这些问题,以符合规范(即保护它在将来不会破坏,因为服务器开始做的事情略有不同):
Authorization
标题中,删除nc
周围的双引号,也可能qop
qop
值。如果它是 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
的方式,您假设摘要总是以这种方式大写,并且 realm
,nonce
等。总是小写的。根据规范,这些都是不区分大小写的 一些不相关的问题:
Digest authentication
?这是HTTPS,因此你也可以Basic authentication
,更方便,使用HTTPS,同样安全。 (在查看了collectcontent之后回答我自己:基本认证显然是not possible)cnonce
对于每个请求都应该是随机的,尤其是您不应该从Wikipedia复制并粘贴它,这会让您更容易受到攻击(但不是问题在这里,因为所有数据都在你的情况下通过SSL)关于如何卷曲 - 试试这个:
curl --data 'id=1234' --digest --user "apikey:pwd" https://abcdefg.gathercontent.com:443/api/0.1/get_pages_by_project/get_me
答案 1 :(得分:3)
这是来自GatherContent的Peter。
第一个非常明显的事情是仅使用get_me
代替get_pages_by_project/get_me
。你在后者中混合了两种不同的东西。 get_me
不需要通过POST发送任何参数,因此您可以删除它们。
另外,请确保您的密码始终为小写x
。
它会改变什么吗?
修改强> 对于任何感兴趣的人,这是我们的API文档: http://gathercontent.helpjuice.com/questions/26611-How-do-I-use-the-API
答案 2 :(得分:1)
express-auth
模块支持多种身份验证方案,包括HTTP摘要。请参阅:https://github.com/ciaranj/express-auth
另一个很好的选择是passport
:https://github.com/jaredhanson/passport
这两个模块中的http-digest示例倾向于关注为node.js应用程序建立身份验证,而不是将身份验证请求转发给第三方。但是,您应该能够使用一点点涂鸦。
如果按下,我会使用护照。提供的示例更清晰,更有文档记录。
希望有帮助...
答案 3 :(得分:0)
我会重新命令你使用mikeal的request模块,它会让它变得更容易和更清洁。
Request还没有对HTTP Auth的支持,但是你只需要设置Authorization
标题。
答案 4 :(得分:0)
尝试urllib,它将与简单而繁琐的身份验证一起使用。