从 APIM 策略获取 Azure 表存储实体

Posted

技术标签:

【中文标题】从 APIM 策略获取 Azure 表存储实体【英文标题】:Get Azure Table Storage Entity from APIM Policy 【发布时间】:2018-03-16 06:17:31 【问题描述】:

我正在尝试使用 API 管理策略获取表实体。所以我在那里生成共享访问签名,但响应了 403 Forbidden。

APIM 政策 (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>

回应


"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"
  
 

但是,我已经验证了下面的php代码可以获取表格实体。

PHP 代码

$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);

所以看来我无法将上面的 php 代码转换为 c#。如果您有任何意见,请帮助我。

【问题讨论】:

【参考方案1】:

请更改这行代码:

using (var encoder = new HMACSHA512(Encoding.UTF8.GetBytes(access_key)))

using (var encoder = new HMACSHA512(Convert.FromBase64String(access_key)))

这应该可以解决问题。

更新

您在错误的地方进行了更改。请看下面的正确代码:

            using (var encoder = new HMACSHA512(Convert.FromBase64String(access_key))) 
                var hash = encoder.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
                var signature = Convert.ToBase64String(hash);
                return signature;
            

【讨论】:

很抱歉回复并感谢您的帮助。但是403错误仍然发生。 *我更新了上面的代码。 您在错误的地方进行了更改:)。请查看我的更新答案。 我修改了我的代码,发现一个错误。哈希算法应该是 256,而不是 512。所以它确实可以。感谢您每次的帮助:)

以上是关于从 APIM 策略获取 Azure 表存储实体的主要内容,如果未能解决你的问题,请参考以下文章

Azure 表存储 - 表服务查询以检索并返回 10 个实体,直到最后一个实体

使用 Azure APIM 策略处理表单数据

如何限制AzCopy从azure表存储中复制的实体数量?

使用 azure 数据工厂管道将 json 对象存储到 azure 表存储实体

Azure APIM 策略

Azure APIM - 策略 - 无法获取有效上下文 - 错误 500 - 对象未设置为对象实例