问题描述
我从 apis.garmin.com(端点 https://apis.garmin.com/wellness-api/rest/activityFile)下载活动。我有一个使用 .net framework 4.7 的控制台应用程序。在 C# 中。
garmin api 上的请求必须使用 OAuth 签名。不幸的是,我们发送到 garmin api 的每个请求都会收到一个 http 代码 401(未经授权)作为响应。
Garmin 支持人员给了我一个如何在 PHP 中创建签名的示例。但是,我无法在 C# 中重写此代码。
我认为问题在于创建signedEncoded,但我不知道我做错了什么。 PHP 示例:
//sample callbackUrl = 'https://healthapi.garmin.com/wellness-api/rest/activityFile?id=32368310271'
$requestBaseUrl = 'https://healthapi.garmin.com/wellness-api/rest/activityFile'; //this is the base URL needed for signature generation,notice there are no parameters (no id)
$id = 32368310271; //this is the id from the sample callbackUrl (activityId)
$oauth_timestamp = time();
$oauth_nonce = time();
$oauth_token = "XXXXXXXXXXX";
$oauth_token_secret= "XXXXXXXXXX";
$oauth_consumer_key = "XXXXXXXXXXX";
$oauth_consumer_secret = "XXXXXXXXXXXXX";
$oauth_signatureMethod = "HMAC-SHA1";
$oauth_version = "1.0";
$base_signature = "GET&" . rawurlencode($requestBaseUrl) ."&" .
rawurlencode("id=$id" . "&oauth_consumer_key=$oauth_consumer_key"
. "&oauth_nonce=$oauth_nonce"
. "&oauth_signature_method=$oauth_signatureMethod"
. "&oauth_timestamp=$oauth_timestamp"
. "&oauth_token=$oauth_token"
. "&oauth_version=$oauth_version");
echo "base_signature: $base_signature \n<br>";
$oauthSig = hash_hmac("SHA1",$base_signature,$oauth_consumer_secret . "&" . $oauth_token_secret,false);
$oauthSig = rawurlencode(base64_encode(pack('H*',$oauthSig)));
echo $oauthSig."<br>";
来自 Garmin 的 PHP 结果: base_signature:GET&HTTPS%3A%2F%2Fapis.garmin.com%2Fwellness-API%2Frest%2FactivityFile&ID%3D185442821846%26oauth_consumer_key%3DXXXXXXXXXXX%26oauth_nonce%3D1622269862%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1622269862%26oauth_token%3DXXXXXXXXXXX%26oauth_version%3D1。 0
OAuth 签名未编码:88913f4d910a3eef46582e2511724dbf69a79f51 OAuth Sig 编码:iJE%2FTZEKPu9GWC4lEXJNv2mnn1E%3D
我的 C# 代码:
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Linq;
namespace OAuthTest
{
class Program
{
void Main()
{
try
{
string oauthToken = "XXXXXXXXXXX";
string consumerKey = "XXXXXXXXXXX";
string consumerSecret = "XXXXXXXXXXX";
string oauthTokenSecret = "XXXXXXXXXXX";
// basesignature I have the same as from garmin example
var baseSignature = "GET&https%3A%2F%2Fapis.garmin.com%2Fwellness-api%2Frest%2FactivityFile&id%3D185442821846%26oauth_consumer_key%3D3DXXXXXXXXXXX%26oauth_nonce%3D1622269862%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1622269862%26oauth_token%3DXXXXXXXXXXX%26oauth_version%3D1.0";
var key = EscapeUriDataStringRfc3986(consumerSecret) + "&" + EscapeUriDataStringRfc3986(oauthTokenSecret);
var keyBytes = Encoding.ASCII.GetBytes(key);
var baseSignatureBytes = Encoding.ASCII.GetBytes(baseSignature);
MemoryStream stream = new MemoryStream(baseSignatureBytes);
string signedEncoded;
using (var hmacsha1 = new HMACSHA1(keyBytes))
{
var signedBytes = hmacsha1.ComputeHash(stream);
signedEncoded = signedBytes.Aggregate("",(s,e) => s + String.Format("{0:x2}",e),s => s);
}
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://apis.garmin.com/wellness-api/rest/activityFile");
httpWebRequest.Method = "GET";
var header =
"OAuth " +
"oauth_nonce=" + SimpleQuote("1622269862") + "," +
"oauth_signature=" + SimpleQuote(signedEncoded) + "," +
"oauth_token=" + SimpleQuote(oauthToken) + "," +
"oauth_consumer_key=" + SimpleQuote(consumerKey) + "," +
"oauth_timestamp=" + SimpleQuote("1622269862") + "," +
"oauth_signature_method=" + SimpleQuote("HMAC-SHA1") + "," +
"oauth_version=" + SimpleQuote("1.0");
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization,header);
var response = httpWebRequest.GetResponse(); // throw exception 401
var responsestream = response.GetResponseStream();
using (responsestream)
{
var reader = new StreamReader(responsestream);
var result = reader.ReadToEnd();
Debug.WriteLine(result);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
private string SimpleQuote(string s) { return '"' + s + '"'; }
private readonly string[] UriRfc3986CharsToEscape = new[] { "!","*","'","(",")" };
private string EscapeUriDataStringRfc3986(string value)
{
StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value));
for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++)
{
escaped.Replace(UriRfc3986CharsToEscape[i],Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
}
return escaped.ToString();
}
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)