You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PHP通过共享访问密钥下载Azure Blob时遇无效头问题求助

解决Azure Blob存储PHP下载的无效头错误

你的代码出现无效头错误,核心原因是SharedKey签名构造不符合Azure规范,以及签名与请求头的版本不一致,以下是修正方案:

问题点分析

  • 签名字符串结构错误:Azure SharedKey要求签名字符串必须按固定顺序包含HTTP方法、多个空值头(对应未设置的Content-Length、Content-MD5等)、排序后的x-ms开头请求头,最后才是资源路径
  • x-ms-version版本不匹配:签名构造时用的是2017-11-09,但请求头里是2017-12-12,两者必须完全一致
  • 头资源拼接方式错误:不能直接把两个x-ms头合并成一个字符串,需要单独按顺序添加到签名数组中

修正后的代码

$containerName = "your-container-name";
$blobName = "your-blob-name";
$accessKey = "your-storage-account-access-key";
$storageAccount = "teststorage";

$URL = "https://{$storageAccount}.blob.core.windows.net/{$containerName}/{$blobName}";
$Date = gmdate('D, d M Y H:i:s \G\M\T');
$apiVersion = "2017-12-12"; // 统一版本号

// 构造签名字符串的数组,严格遵循Azure SharedKey顺序
$arraysign = array();
$arraysign[] = 'GET';                    // HTTP方法
$arraysign[] = '';                      // Content-Encoding(空值)
$arraysign[] = '';                      // Content-Language(空值)
$arraysign[] = '';                      // Content-Length(空值,GET请求可忽略)
$arraysign[] = '';                      // Content-MD5(空值)
$arraysign[] = '';                      // Content-Type(空值)
$arraysign[] = '';                      // Date(空值,因为用了x-ms-date)
$arraysign[] = '';                      // If-Modified-Since(空值)
$arraysign[] = '';                      // If-Match(空值)
$arraysign[] = '';                      // If-None-Match(空值)
$arraysign[] = '';                      // If-Unmodified-Since(空值)
$arraysign[] = '';                      // Range(空值)
// 添加x-ms开头的请求头,必须按小写排序后添加
$arraysign[] = "x-ms-date:{$Date}";
$arraysign[] = "x-ms-version:{$apiVersion}";
// 添加资源路径:/存储账户名/容器名/Blob名
$arraysign[] = "/{$storageAccount}/{$containerName}/{$blobName}";

// 拼接签名字符串,用换行符分隔
$str2sign = implode("\n", $arraysign);

// 生成签名:注意不要urldecode,直接用原始字符串计算HMAC
$sig = base64_encode(hash_hmac('sha256', utf8_encode($str2sign), base64_decode($accessKey), true));

$authHeader = "SharedKey {$storageAccount}:{$sig}";

// 请求头必须和签名里的参数一致
$headers = [
    'Authorization: ' . $authHeader,
    'x-ms-date: ' . $Date,
    'x-ms-version: ' . $apiVersion,
];

// 执行下载请求(示例用curl)
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 生产环境建议开启
$blobContent = curl_exec($ch);
curl_close($ch);

// 保存到本地文件
file_put_contents('/path/to/local/file', $blobContent);

关键说明

  • 签名数组顺序不能乱:Azure对签名字符串的顺序有严格要求,必须按照规定顺序填充,未设置的头留空字符串
  • 版本号统一:x-ms-version在签名构造和请求头中必须完全相同
  • 不要对签名字符串做urldecode:原始字符串直接用于HMAC计算即可,urldecode会破坏签名结构
  • 生产环境建议保留CURLOPT_SSL_VERIFYPEER为true,确保SSL安全

内容的提问来源于stack exchange,提问作者User User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:05:31