首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算oauth签名

计算oauth签名
EN

Stack Overflow用户
提问于 2015-03-07 00:57:39
回答 1查看 3.5K关注 0票数 4

我正在尝试一些特定的东西,即尝试调用REST。我一直在跟踪这些使用说明

我一直非常小心,以确保我正在创建正确的“签名基字符串”。他们定义它是这样创建的:

(HTTP方法)&(请求URL)和(规范化参数)

您可以在我的代码中反复检查是否需要,但我非常肯定它是好的。

我遇到的问题是创建他们所谓的"oauth签名“,而我的签名与他们的签名不匹配。它们应该是这样创造的:

使用RFC2104定义的HMAC-SHA1 1签名算法对请求进行签名,其中文本是签名基字符串,密钥是由“&”字符分隔的“消费者秘密”和“访问秘密”的连接值(显示&“”,即使访问秘密是空的,因为有些方法不需要访问令牌)。 计算出的摘要八进制字符串,首先每个RFC2045使用base64 64编码,然后使用RFC3986百分比编码(%xx)机制转义,即oauth_signature。

我在代码中如下所示:

代码语言:javascript
复制
var oauthSignature = CryptoJS.HmacSHA1(signatureBaseString, sharedSecret+"&");
var oauthSignature64 = encodeURIComponent(CryptoJS.enc.Base64.stringify(oauthSignature));
console.log("hash in 64: " + oauthSignature64);

我正在使用谷歌的CryptoJS库。我以签名基字符串作为文本,然后将我的使用者秘密作为与"&“连接的密钥,我没有访问密钥,它不是必需的,但没关系。然后我以64为基础对哈希的结果进行编码,在此之后,我对它进行了URI编码,请一些人检查一下我对它的理解,以及我在使用这个库的代码中使用/表示它的用法/表示,我认为这就是我的问题所在。

这是我的完整代码:

代码语言:javascript
复制
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
});

我已小心确保我张贴的参数是按字典顺序排列的,而且我非常肯定这是正确的。

我得到的回应是:

无效签名: oauth_signature 'RWeFME4w2Obzn2x50xsXujAs1yI=‘

很明显

  1. 我还没有理解API中提供的说明
  2. 或者我已经理解了它们,但我没有在代码中用这种方式来表达它们
  3. 或以上两种情况
  4. 或者我犯了一些我看不见的微妙的错误

我真的很希望你能检查一下,这需要一段时间。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-14 20:16:41

嗯.我做到了,但不是我认为我最终会这么做的方式,我花了几个小时的时间尝试它,然后使用JQuery,最后我尝试了Node,它起作用了,下面是两个工作示例,一个是food.get,另一个是foods.search

food.get示例

代码语言:javascript
复制
    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");
    });

foods.search示例

代码语言:javascript
复制
    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");
    });

非常抱歉,任何人使用角或JQuery,如果我有一分钟或两分钟的空闲时间,我会尝试它的角度,也是任何人使用角如果你得到CORS相关的错误,只要启动铬如下:

chromium-browser --disable-web-security --我在终端上做这件事,或者在窗口上添加一些铬快捷方式,就像快速工作一样,希望它能帮助到其他人。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28910178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档