我已经阅读了大量的文章、实现并搜索了网络,但我找不到任何有用的东西,并且肯定错过了一些非常简单的“签名”。
场景: 我需要制作一个自动化工具,它将获取对话 ID(在我的例子中),检查 API 响应中的状态,然后决定下一步的操作。即发送通知等
问题: 相同的 API 在 Postman 中运行良好,但当我尝试在 C#.NET 中实现它时,它总是给出与下面给出的相同结果。尽管我尝试过不同的代码和库。
错误:
{"code":"0005","debugMessage":"The server will not process the request because it is unauthenticated. Reason: oauth_problem=signature_invalid&oauth_problem_advice=the oauth_signature is invalid"}
代码-调用函数:
string domainUrl = @"https://xyz-my-server-domain.com/";
string accountId = "XXXXXXXX";
string appKey = "05119901595a443d8XXXXXXXXX";
string appSecret = "54fdc15a0fXXXXXX";
string token = "ae4e2979958b401c97XXXXXXXXXX";
string tokenSecret = "4b075XXXXXXXXXXXX";
Uri uri = new Uri(domainUrl + @"/conversations/conversation/search");
OAuthBase oauthBase = new OAuthBase();
string nonce = oauthBase.GenerateNonce();
string timeStamp = oauthBase.GenerateTimeStamp();
string authSignature = "";
/// <summary>
/// Everything seems ok but still something is wrong here...
/// </summary>
string encodedUrl = GetOAuthSignature(uri, appKey, appSecret, token, tokenSecret, timeStamp, nonce, out authSignature);
var client = new RestClient(encodedUrl);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var body = @"{ ..... my request body ..... }";
request.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
GetOAuthSignature 函数:
private static string GetOAuthSignature(Uri uri, string consumerKey, string consumerSecret, string token, string tokenSecret, string timeStamp, string nonce, out string signature)
{
OAuthBase oAuth = new OAuthBase();
string normalizedUrl = "";
string normalizedRequestParameters = "";
/// <summary>
/// Allowed Signature Methods: HMAC-SHA256 and HMAC-SHA1 only for this API.
/// </summary>
string signatureStr = oAuth.GenerateSignature(uri, consumerKey, string.Empty, token, string.Empty, "POST", timeStamp, nonce, OAuthBase.SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
signatureStr = HttpUtility.UrlEncode(signatureStr);
StringBuilder sb = new StringBuilder(uri.ToString());
sb.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
sb.AppendFormat("oauth_token={0}&", token);
/// <summary>
/// Allowed Signature Methods: HMAC-SHA256 and HMAC-SHA1 only for this API.
/// </summary>
sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
sb.AppendFormat("oauth_nonce={0}&", nonce);
sb.AppendFormat("oauth_version={0}&", "1.0");
sb.AppendFormat("oauth_signature={0}", signatureStr);
signature = signatureStr;
return sb.ToString();
}
我怀疑,我在 GetOAuthSignature 中做错了什么。
我自己已经解决了。我继续阅读有关 OAuth Signature 的随机文章,发现RFC3986规范要求以大写字母进行编码。
失败原因: 我的签名采用“小写”大小写进行编码。即
****************zHqKh6Yk%2bUPPERcKzwA1F8 %3d
虽然此 API 规范仅支持
情况:
****************zHqKh6Yk%2BIETF 草案cKzwA1F8 %3D
后来我发现
具有相同的信息(之前错过了几次,而且我实际上对这个方法规范一无所知)。只需转到第 3.6 节即可。百分比编码,提到过:
用于表示编码字符的两个十六进制字符必须为大写。