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

使用Azurite执行PUT操作时共享密钥生成失败,返回403错误

问题描述

尝试使用Azurite发起PUT Blob请求,参数如下:

account = "devstoreaccount1"
key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" 
api_version = "2021-06-08"
block_type = "BlockBlob"

构造的签名字符串:

string_to_sign = (f"PUT\n"  # HTTP method
                 f"\n"  # Content-Encoding
                 f"\n"  # Content-Language
                 f"0\n"  # Content-Length
                 f"\n"  # Content-MD5
                 f"\n"  # Content-Type
                 f"\n"  # Date
                 f"\n"  # If-Modified-Since
                 f"\n"  # If-Match
                 f"\n"  # If-None-Match
                 f"\n"  # If-Unmodified-Since
                 f"\n"  # Range
                 f"x-ms-date:{date_str}\n"
                 f"x-ms-version:{api_version}\n"
                 f"x-ms-blob-type:{block_type}\n"
                 f"/{account}/{container}/{blob}")

每次请求均返回403认证失败,错误信息:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Error>
    <Code>AuthorizationFailure</Code>
    <Message>Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.
RequestId:35ee2117-c03a-417d-84dd-be4a0b4d1163
Time:2024-10-29T16:04:11.193Z</Message>
</Error>

使用的Python代码:

import hmac
import hashlib
import base64
from datetime import datetime

def main():
    authorization, date, api_version = blobs()

    print(f"Authorization: {authorization}")
    print(f"Date: {date}")
    print(f"API Version: {api_version}")
    input("Press any key to exit...")


def blobs():
    account = "devstoreaccount1"
    key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="  # Replace with your access key
    container = "container" 
    blob = "file.txt" 
    api_version = "2021-06-08"
    block_type = "BlockBlob"

    dt = datetime.utcnow()
    date_str = dt.strftime('%a, %d %b %Y %H:%M:%S GMT')

    string_to_sign = (f"PUT\n"  # HTTP method
                     f"\n"  # Content-Encoding
                     f"\n"  # Content-Language
                     f"0\n"  # Content-Length
                     f"\n"  # Content-MD5
                     f"\n"  # Content-Type
                     f"\n"  # Date
                     f"\n"  # If-Modified-Since
                     f"\n"  # If-Match
                     f"\n"  # If-None-Match
                     f"\n"  # If-Unmodified-Since
                     f"\n"  # Range
                     f"x-ms-date:{date_str}\n"
                     f"x-ms-version:{api_version}\n"
                     f"x-ms-blob-type:{block_type}\n"
                     f"/{account}/{account}/{container}/{blob}")

    signature = sign_this(string_to_sign, key)

    # Updated Authorization format
    authorization = f"SharedKey {account}:{signature}"

    return authorization, date_str, api_version


def sign_this(string_to_sign, key):
    decoded_key = base64.b64decode(key)
    string_to_sign = string_to_sign.encode('utf-8')

    hmac_sha256 = hmac.new(decoded_key, string_to_sign, hashlib.sha256)
    signature = base64.b64encode(hmac_sha256.digest()).decode('utf-8')

    return signature


if __name__ == "__main__":
    main()

将代码生成的Authorization值替换到Postman的请求头中,问题依旧,请问哪里出错了?


问题排查与修复

你的代码和签名字符串构造存在两个关键错误:

1. 资源路径重复账户名

代码中构造的路径为/{account}/{account}/{container}/{blob},多写了一个{account},导致路径变成/devstoreaccount1/devstoreaccount1/container/file.txt,与实际请求的资源路径不匹配,直接导致签名验证失败。正确的路径格式应为/{account}/{container}/{blob}。

2. x-ms头部排序错误

Azure Storage的SharedKey认证要求所有x-ms开头的请求头必须按字典序排序后加入签名字符串。你当前的顺序是x-ms-date、x-ms-version、x-ms-blob-type,正确的字典序应为x-ms-blob-type、x-ms-date、x-ms-version,顺序错误会导致签名不匹配。

修复后的签名字符串

修改上述两个问题后的代码片段:

string_to_sign = (f"PUT\n"
                 f"\n"  # Content-Encoding
                 f"\n"  # Content-Language
                 f"0\n"  # Content-Length
                 f"\n"  # Content-MD5
                 f"\n"  # Content-Type
                 f"\n"  # Date
                 f"\n"  # If-Modified-Since
                 f"\n"  # If-Match
                 f"\n"  # If-None-Match
                 f"\n"  # If-Unmodified-Since
                 f"\n"  # Range
                 f"x-ms-blob-type:{block_type}\n"
                 f"x-ms-date:{date_str}\n"
                 f"x-ms-version:{api_version}\n"
                 f"/{account}/{container}/{blob}")

额外验证点

  • 确保请求时的x-ms-date与签名时使用的date_str完全一致,时间差不能超过15分钟(Azure的时间窗口限制);
  • 确认请求头包含所有签名字符串中的x-ms头部,不能多也不能少;
  • 检查Azurite服务是否正常运行,端点和端口配置是否正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 17:32:04