我正在尝试一些特定的东西,即尝试调用 REST API。我一直在关注这些instructions .
我一直非常小心地确保我正确创建了“签名基本字符串”。他们定义它是这样创建的:
(HTTP Method)&(Request URL)&(Normalized Parameters)
您可以仔细检查是否需要在我的代码中,但我非常确定它没问题。
我遇到的问题是创建他们所谓的“oauth 签名”,而我的与他们的不匹配。他们应该像这样创建:
Use the HMAC-SHA1 signature algorithm as defined by the [RFC2104] to sign the request where text is the Signature Base String and key is the concatenated values of the Consumer Secret and Access Secret separated by an '&' character (show '&' even if Access Secret is empty as some methods do not require an Access Token).
The calculated digest octet string, first base64-encoded per [RFC2045], then escaped using the [RFC3986] percent-encoding (%xx) mechanism is the oauth_signature.
我在我的代码中这样表达:
var oauthSignature = CryptoJS.HmacSHA1(signatureBaseString, sharedSecret+"&");
var oauthSignature64 = encodeURIComponent(CryptoJS.enc.Base64.stringify(oauthSignature));
console.log("hash in 64: " + oauthSignature64);
我正在使用 Google 的 CryptoJS 库。我将签名基本字符串作为文本,然后将我的消费者 secret 作为与“&”连接的 key ,我没有访问 key ,它不是必需的,但没关系。然后我对散列的结果进行 base 64 编码,然后我对它进行 URI 编码,请有些人理智地检查我对它的理解以及我在使用这个库的代码中的使用/表达,我认为这就是我的问题所在。这是我的完整代码:
var fatSecretRestUrl = "http://platform.fatsecret.com/rest/server.api";
var d = new Date();
var sharedSecret = "xxxx";
var consumerKey = "xxxx";
//this is yet another test tyring to make this thing work
var baseUrl = "http://platform.fatsecret.com/rest/server.api?";
var parameters = "method=food.search&oauth_consumer_key="+consumerKey+"&oauth_nonce=123&oauth_signature_method=HMAC-SHA1&oauth_timestamp="+getTimeInSeconds()+"&oauth_version=1.0&search_expression=banana";
var signatureBaseString = "POST&" + encodeURIComponent(baseUrl) + "&" + encodeURIComponent(parameters);
console.log("signature base string: " + signatureBaseString);
var oauthSignature = CryptoJS.HmacSHA1(signatureBaseString, sharedSecret+"&");
var oauthSignature64 = encodeURIComponent(CryptoJS.enc.Base64.stringify(oauthSignature));
console.log("hash in 64: " + oauthSignature64);
var testUrl = baseUrl+"method=food.search&oauth_consumer_key=xxxx&oauth_nonce=123&oauth_signature="+oauthSignature64+"&oauth_signature_method=HMAC-SHA1&oauth_timestamp="+getTimeInSeconds()+"&oauth_version=1.0&search_expression=banana";
console.log("final URL: " + testUrl);
var request = $http({
method :"POST",
url: testUrl
});
我已注意确保我发布的参数按字典顺序排列,并且我非常确定它是正确的。我得到的回应是:
Invalid signature: oauth_signature 'RWeFME4w2Obzn2x50xsXujAs1yI='
那么清楚要么
我真的很感谢进行健全性检查,这需要一段时间。
最佳答案
嗯......我做到了,但不是我认为我最终会这样做的方式,我花了几个小时用 angular 和 JQuery 尝试它,然后最后我尝试了 Node JS 并且它起作用了,这里有两个工作示例,一个与 food.get
另一个是 foods.search
food.get 示例
var rest = require('restler'),
crypto = require('crypto'),
apiKey = 'xxxx',
fatSecretRestUrl = 'http://platform.fatsecret.com/rest/server.api',
sharedSecret = 'xxxx',
date = new Date;
// keys in lexicographical order
var reqObj = {
food_id: '2395843', // test query
method: 'food.get',
oauth_consumer_key: apiKey,
oauth_nonce: Math.random().toString(36).replace(/[^a-z]/, '').substr(2),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: Math.floor(date.getTime() / 1000),
oauth_version: '1.0'
};
// make the string...got tired of writing that long thing
var paramsStr = '';
for (var i in reqObj) {
paramsStr += "&" + i + "=" + reqObj[i];
}
// had an extra '&' at the front
paramsStr = paramsStr.substr(1);
var sigBaseStr = "GET&"
+ encodeURIComponent(fatSecretRestUrl)
+ "&"
+ encodeURIComponent(paramsStr);
// no access token but we still have to append '&' according to the instructions
sharedSecret += "&";
var hashedBaseStr = crypto.createHmac('sha1', sharedSecret).update(sigBaseStr).digest('base64');
// Add oauth_signature to the request object
reqObj.oauth_signature = hashedBaseStr;
rest.get(fatSecretRestUrl, {
data: reqObj,
}).on('complete', function(data, response) {
console.log(response);
console.log("DATA: " + data + "\n");
});
food.search 示例
var rest = require('restler'),
crypto = require('crypto'),
apiKey = 'xxxx',
fatSecretRestUrl = 'http://platform.fatsecret.com/rest/server.api',
sharedSecret = 'xxxx',
date = new Date;
// keys in lexicographical order
var reqObj = {
method: 'foods.search',
oauth_consumer_key: apiKey,
oauth_nonce: Math.random().toString(36).replace(/[^a-z]/, '').substr(2),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: Math.floor(date.getTime() / 1000),
oauth_version: '1.0',
search_expression: 'mcdonalds' // test query
};
// make the string...got tired of writing that long thing
var paramsStr = '';
for (var i in reqObj) {
paramsStr += "&" + i + "=" + reqObj[i];
}
// had an extra '&' at the front
paramsStr = paramsStr.substr(1);
var sigBaseStr = "POST&"
+ encodeURIComponent(fatSecretRestUrl)
+ "&"
+ encodeURIComponent(paramsStr);
// again there is no need for an access token, but we need an '&' according to the instructions
sharedSecret += "&";
var hashedBaseStr = crypto.createHmac('sha1', sharedSecret).update(sigBaseStr).digest('base64');
// Add oauth_signature to the request object
reqObj.oauth_signature = hashedBaseStr;
rest.post(fatSecretRestUrl, {
data: reqObj,
}).on('complete', function(data, response) {
console.log(response);
console.log("DATA: " + data + "\n");
});
真的很抱歉任何使用 Angular 或 JQuery 的人,如果我有一两分钟的空闲时间,我会用 angular 尝试一下,如果您遇到与 CORS 相关的错误,任何使用 angular 的人也只需像这样启动 chrome:
chromium-browser --disable-web-security
- 我在终端上做这个或将该扩展程序添加到 Windows 上的某些 chrome 快捷方式,就像快速解决方法一样,希望它可以帮助那里的任何人。
关于rest - 计算 oauth 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28910178/