我的 iPhone 应用程序中遇到了 FatSecret REST api 的无效 oauth 签名问题。以下是回复
error = {
code = 8;
message = "Invalid signature: oauth_signature 'giWu0JtjgG3OBqD_sBCByz-Q2Gk='";
};
我正在使用 HMAC_SHA1 创建签名请求,对于某些搜索,它会返回正确的签名,在某些情况下,它会针对 food.get 和 food.search 方法给出上述错误
任何帮助都会有用 预先感谢!
我发现使用 FatSecret 进行 oauth 相当乏味。当您向他们发送有关 oauth 问题的电子邮件时,他们会将您引导至他们的 google 群组。最终,我也无法在那里获得太多帮助,但当我最终弄清楚时,我确实发布了我的实现。
这是一个完整的 node.js food.search() 实现——可能值得一看
发生这种情况是因为 oauth 签名编码错误。生成的摘要应根据 RFC2045 协议进行 Base64 编码。
通过在生成 o_auth 签名时将出现的字符串“_”替换为“/”,将“-”替换为“+”得到解决方案。
希望它能帮助其他用户:)
我发现如果base64编码的oAuth签名有任何空格(RFC3986 url编码后的“+”),我也会收到无效的签名响应。我检查了 oAuth 签名字符串是否包含违规字符,如果包含,我重新生成了 oAuth 签名。我使用 1970 年以来的时间间隔作为时间戳(根据 API 的要求)和随机数,因此重新创建随机数和时间戳直到不存在空格是一个简单的问题。
现在,您应该可以在 Postman 中发送请求了。此设置可确保客户端 ID 和客户端密钥作为基本身份验证凭据发送,并且必要的参数包含在请求正文中。
请将
我在收到同样的错误时遇到了这篇文章。事实证明,在我的例子中,错误是由于没有在文档中注意到在对签名进行编码之前需要将“&”添加到 API_SECRET 的末尾。为了帮助将来的人,我发布我的解决方案:
import crypto from 'crypto';
import { FS_ID, FS_OA1_API_KEY } from '$env/static/private';
import { v4 as uuidv4 } from 'uuid';
export default class FatSecretOauth1 {
constructor(httpMethod, url, inputParameters) {
this.requestUrl = url;
this.httpMethod = httpMethod.toUpperCase();
this.inputParameters = {
...inputParameters,
format: 'json',
oauth_consumer_key: FS_ID,
oauth_nonce: uuidv4(),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: Math.floor(new Date().getTime()),
oauth_version: '1.0'
};
this.paramString = this.buildRequestParameterString();
this.signature = this.buildSignature();
return { paramString: this.paramString, signature: this.signature };
}
buildSignature() {
let method = encodeURIComponent(this.httpMethod);
let url = encodeURIComponent(this.requestUrl);
let params = encodeURIComponent(this.paramString);
let signature = crypto
.createHmac('sha1', `${FS_OA1_API_KEY}&`) //<-- My error was here with the "&"
.update(`${method}&${url}&${params}`)
.digest()
.toString('base64');
return encodeURIComponent(signature);
}
buildRequestParameterString() {
let params = '';
Object.entries(this.inputParameters)
.sort()
.forEach((cur) => (params += `&${encodeURI(cur[0])}=${encodeURI(cur[1])}`));
params = params.substring(1);
return params;
}
}
下面是使用参数字符串和签名的获取。
const searchByID = {
method: 'food.get.v4',
food_id: 27443
};
let url = 'https://platform.fatsecret.com/rest/server.api';
let httpMethod = 'POST';
const result = new FatSecretOauth1(httpMethod, url, searchByID);
const response = await fetch(
`${url}?${result.paramString}&oauth_signature=${result.signature}`,
{
method: httpMethod
});
const data = await response.json();
console.log('fetch Data: ', data);
return { data: data.food };
}
我希望这可以在将来节省某人的时间。