I am trying to get table entity using API Management policy. So I generate shared access signature at there but the 403 Forbidden is responded.
APIM Policy (C#)
<set-variable name="presentTime" value="@( (DateTime.UtcNow).ToString("ddd, dd MMM yyyy hh:mm:ss ") + "GMT" )" />
<set-variable name="getTableEntityToken" value="@{
var storage_account = "XXXXXX";
var table = "XXXXXXXX";
var access_key = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
var canonicalized_headers = "\n/" + storage_account + "/" + table;
string[] stringToSignArray = {
// VERB
"GET",
// Content-MD5
"",
// Content-Type
"",
// Date
context.Variables.GetValueOrDefault<string>("presentTime"),
};
string stringToSign = String.Join("\n", stringToSignArray) + canonicalized_headers;
using (var encoder = new HMACSH256(Convert.FromBase64String(access_key))) {
var hash = encoder.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
var signature = Convert.ToBase64String(hash);
return signature;
}
}" />
<set-header name="Authorization" exists-action="override">
<value>@( "SharedKey " + "XXXXXXX:" + context.Variables.GetValueOrDefault<string>("getTableEntityToken") )</value>
</set-header>
<set-header name="x-ms-date" exists-action="override">
<value>@( context.Variables.GetValueOrDefault<string>("presentTime") )</value>
</set-header>
<set-header name="x-ms-version" exists-action="override">
<value>2015-12-11</value>
</set-header>
<set-header name="Accept" exists-action="override">
<value>application/json;odata=nometadata</value>
</set-header>
Response
{
"odata.error": {
"code": "AuthenticationFailed",
"message": {
"lang": "en-US",
"value": "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:21877d9e-a002-0022-0dea-bc7d70000000\nTime:2018-03-16T05:50:10.3226402Z"
}
}
}
However, I've already verified that php code below can get table entity.
PHP Code
$account = "XXXXXX";
$tablestoragename = "XXXXXXX";
$accessKey = "XXXXXXXXX";
$date = gmdate('D, d M Y H:i:s T',time());
$api_version = "2015-12-11";
$url = "https://$account.table.core.windows.net/$tablestoragename";
$method = "GET";
$accept = "application/json;odata=nometadata";
$stringToSign = [
// VERB
$method,
// Content-MD5
'',
// Content-Type
'',
// Date
$date,
];
$stringToSign = array_merge($stringToSign, ["/$account/$tablestoragename"]);
$stringToSign = implode("\n", $stringToSign);
$signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));
$headers = [
"x-ms-date:{$date}",
"x-ms-version:$api_version",
"Authorization:SharedKey $account:{$signature}",
"Accept:$accept",
];
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
);
$proxy_options = array(
CURLOPT_PROXY => 'http://XXXXXXXXXX',
CURLOPT_PROXYPORT => 'XXXX',
);
curl_setopt_array($ch, $proxy_options);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
var_dump($response);
echo curl_error($ch);
curl_close($ch);
So it seems that I cannot convert above php code to c#. If you have any opinions, please help me.
Please change this line of code:
using (var encoder = new HMACSHA512(Encoding.UTF8.GetBytes(access_key)))
to
using (var encoder = new HMACSHA512(Convert.FromBase64String(access_key)))
And that should solve the problem.
UPDATE
You made changes in the wrong place. Please see the correct code below:
using (var encoder = new HMACSHA512(Convert.FromBase64String(access_key))) {
var hash = encoder.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
var signature = Convert.ToBase64String(hash);
return signature;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.