PHP和cURL将json插入Azure表存储

5tmbdcev  于 2023-03-03  发布在  PHP
关注(0)|答案(1)|浏览(124)

我们正在尝试将一个json对象插入到Azure表中,但在进行rest调用时,我们不断收到以下异常:

  • 服务器无法验证请求。请确保Authorization标头的值(包括签名)格式正确。*

创建的授权标头与https://learn.microsoft.com/en-us/azure/storage/common/storage-rest-api-auth?toc=%2Fazure%2Fstorage%2Ftables%2Ftoc.json中给定的格式匹配

"SharedKey <storage account name>:<signature>"

稍微修改一下,我们就可以让这个基本脚本在blob存储中创建一个blob,但是我们需要将json对象保存到表存储中。下面的解决方案适用于blob存储,但是我们还没有让它适用于表存储:Simple PHP cURL file upload to Azure storage blob
我们相信下面的代码段应该可以工作,但是,我们仍然会遇到上面提到的授权异常。

function sendTableEntries($jsonData, $storageAccount, $tablename, $destinationURL, $accesskey) {

    echo $jsonData, $storageAccount, $tablename, $destinationURL, $accesskey;
    $currentDate = gmdate("D, d M Y H:i:s T", time());
    
    $contLen = strlen($jsonData);

    $headerResource = "x-ms-blob-cache-control:max-age=3600\nx-ms-blob-type:BlockBlob\nx-ms-date:$currentDate\nx-ms-version:2017-07-29";
    $urlResource = "/$storageAccount/$tablename";

    $arraysign = array();
    $arraysign[] = 'POST';               /*HTTP Verb*/  
    $arraysign[] = '';                  /*Content-Encoding*/  
    $arraysign[] = '';                  /*Content-Language*/  
    $arraysign[] = $contLen;            /*Content-Length (include value when zero)*/  
    $arraysign[] = '';                  /*Content-MD5*/  
    $arraysign[] = 'application/json';  /*Content-Type*/  
    $arraysign[] = '';                  /*Date*/  
    $arraysign[] = '';                  /*If-Modified-Since */  
    $arraysign[] = '';                  /*If-Match*/  
    $arraysign[] = '';                  /*If-None-Match*/  
    $arraysign[] = '';                  /*If-Unmodified-Since*/  
    $arraysign[] = '';                  /*Range*/  
    $arraysign[] = $headerResource;     /*CanonicalizedHeaders*/
    $arraysign[] = $urlResource;        /*CanonicalizedResource*/

    $str2sign = implode("\n", $arraysign);

    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true));  
    $authHeader = "SharedKey $storageAccount:$sig";
    
    //echo "sig is " . $sig;
    //echo " Auth header is " . $authHeader;

    $headers = array( 'Authorization: ' . $authHeader,
        'x-ms-blob-cache-control: max-age=3600',
        'x-ms-blob-type: BlockBlob',
        'x-ms-date: ' . $currentDate,
        'x-ms-version: 2017-07-29',
        'Content-Type: application/json',
        'Content-Length: ' . $contLen );

    $ch = curl_init($destinationURL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSLVERSION, 6);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
    
    $result = curl_exec($ch);
    
    echo ('Result<br/>');
    print_r($result);

    echo ('Error<br/>');
    print_r(curl_error($ch));

    curl_close($ch);
}

$accesskey = "ACCESSKEY";
$storageAccount = 'storageaccount';
$tablename = 'tablename';

$temp = array();
$temp["PartitionKey"] = "5432";
$temp["RowKey"] =  "234235";
$temp["value"] = 3455;
$temp["valid"] = 1;

$content = json_encode($temp);

$destinationTable = "https://$storageAccount.table.core.windows.net/$tablename";

sendTableEntries($content, $storageAccount, $tablename, $destinationTable, $accesskey);

有没有人知道上面的代码出了什么问题,这样我们才能成功地将json插入到azure表中?请注意,php版本太旧,无法支持Azure SDK for PHP。

fumotvh3

fumotvh31#

解决方案是将$arraysign中的元素数量减少到这里列出的元素数量,正如上面注解中建议的那样。
以下是一个工作示例:

function sendTableEntries($jsonData, $storageAccount, $tablename, $destinationURL, $accesskey) {

    $currentDate = gmdate("D, d M Y H:i:s T", time());

    $urlResource = "/$storageAccount/$tablename";

    $arraysign = array();
    $arraysign[] = 'POST';               /*HTTP Verb*/ 
    $arraysign[] = '';                  /*Content-MD5*/  
    $arraysign[] = 'application/json';  /*Content-Type*/  
    $arraysign[] = $currentDate;        /*Date*/  
    $arraysign[] = $urlResource;        /*CanonicalizedResource*/

    $str2sign = implode("\n", $arraysign);

    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true));  
    $authHeader = "SharedKey $storageAccount:$sig";

    $headers = array( 'Authorization: ' . $authHeader,
        'x-ms-date: ' . $currentDate,
        'x-ms-version: 2021-08-06',
        'Content-Type: application/json');

    $ch = curl_init($destinationURL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSLVERSION, 6);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);    
    $result = curl_exec($ch);
    
    echo ('Result<br/>');
    print_r($result);

    echo ('Error<br/>');
    print_r(curl_error($ch));

    curl_close($ch);
}

$accesskey = "ACCESSKEY";
$storageAccount = 'storageaccount';
$tablename = 'tablename';

$temp = array();
$temp["PartitionKey"] = "5432";
$temp["RowKey"] =  "234235";
$temp["value"] = 3455;
$temp["valid"] = 1;

$content = json_encode($temp);

$destinationTable = "https://$storageAccount.table.core.windows.net/$tablename";

sendTableEntries($content, $storageAccount, $tablename, $destinationTable, $accesskey);

相关问题