python - Azure blob 共享 key 创建 403 错误获取

标签 python python-3.x azure rest azure-blob-storage

我想使用共享 key 授权使用 python 代码创建 Azure blob 容器,

我收到以下错误:

b'\xef\xbb\xbf<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:9e524b5e-301e-0051-4aa4-45750000\nTime:2023-02-21T03:27:02.8384023Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request \'xxxxxxxxxxxxxxxx\' is not the same as any computed signature. Server used following string to sign: \'PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Tue, 21 Feb 2023 03:27:01 GMT\nx-ms-version:2020-04-08\n/blobmediapedevwus2/mycontainer\nrestype:container\'.</AuthenticationErrorDetail></Error>'

如何解决这个问题?

下面是Python代码:

import requests
import datetime
import hmac
import hashlib
import base64

# Set the storage account name and access key
STORAGE_ACCOUNT_NAME = 'vidyaflowerapp01'
STORAGE_ACCOUNT_KEY = "xxxxxxxxxx"

# Set the container name
CONTAINER_NAME = 'test'

# Set the request method and version
REQUEST_METHOD = 'PUT'
REQUEST_VERSION = '2020-04-08'

# Set the request date
REQUEST_DATE = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')

CANONICALIZED_HEADERS = f'x-ms-date:{REQUEST_DATE}\nx-ms-version:{REQUEST_VERSION}\n'


# Set the canonicalized resource string
CANONICALIZED_RESOURCE = f'/{STORAGE_ACCOUNT_NAME}/{CONTAINER_NAME}\nrestype:container'

VERB = 'PUT'
Content_Encoding = ''
Content_Language = ''
Content_Length = ''
Content_MD5 = ''
Content_Type = ''
Date = ''
If_Modified_Since = ''
If_Match = ''
If_None_Match = ''
If_Unmodified_Since = ''
Range = ''
CanonicalizedHeaders = CANONICALIZED_HEADERS
CanonicalizedResource = CANONICALIZED_RESOURCE

STRING_TO_SIGN = (VERB + '\n' + Content_Encoding + '\n' + Content_Language + '\n' +
                Content_Length + '\n' + Content_MD5 + '\n' + Content_Type + 
                Date + '\n' + If_Modified_Since + '\n' + If_Match + '\n' +
                If_None_Match + '\n' + If_Unmodified_Since + '\n' + Range + '\n' +
                CanonicalizedHeaders + CanonicalizedResource)
signature = base64.b64encode(hmac.new(base64.b64decode(STORAGE_ACCOUNT_KEY), msg=STRING_TO_SIGN.encode('utf-8'), digestmod=hashlib.sha256).digest()).decode()

# Generate the authorization header
auth_header = f'SharedKey {STORAGE_ACCOUNT_NAME}:{signature}'


# Set the request URL
request_url = f'https://{STORAGE_ACCOUNT_NAME}.blob.core.windows.net/{CONTAINER_NAME}?restype=container'

# Set the request headers
request_headers = {
    'x-ms-date': REQUEST_DATE,
    'x-ms-version': REQUEST_VERSION,
    'Authorization': auth_header
}

# Send the request
response = requests.put(request_url, headers=request_headers)
print(response.content)
print(response.status_code)

上面的代码使用共享 key 授权来发出请求,我们必须替换 access-key 和存储帐户才能测试

当前回复:403 预期回复:201

最佳答案

补充@Gaurav Mantri 所说的内容,您收到此消息是因为授权 header 的格式不正确。从我这边复制后,当我在构建签名时用空字符串替换 DateContent Length 时,效果很好。下面是对我有用的完整代码。

import requests
import datetime
import hmac
import hashlib
import base64

# Set the storage account name and access key
STORAGE_ACCOUNT_NAME = '<XXX>'
STORAGE_ACCOUNT_KEY = "<XXX>"

# Set the container name
CONTAINER_NAME = 'mycontainer522'

# Set the request method and version
REQUEST_METHOD = 'PUT'
REQUEST_VERSION = '2020-04-08'

# Set the request date
REQUEST_DATE = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')

CANONICALIZED_HEADERS = f'x-ms-date:{REQUEST_DATE}\nx-ms-version:{REQUEST_VERSION}\n'


# Set the canonicalized resource string
CANONICALIZED_RESOURCE = f'/{STORAGE_ACCOUNT_NAME}/{CONTAINER_NAME}\nrestype:container'

VERB = 'PUT'
Content_Encoding = ''
Content_Language = ''
Content_Length = ''
Content_MD5 = ''
Content_Type = ''
Date = ''
If_Modified_Since = ''
If_Match = ''
If_None_Match = ''
If_Unmodified_Since = ''
Range = ''
CanonicalizedHeaders = CANONICALIZED_HEADERS
CanonicalizedResource = CANONICALIZED_RESOURCE

STRING_TO_SIGN = (VERB + '\n' + Content_Encoding + '\n' + Content_Language + '\n' +
                Content_Length + '\n' + Content_MD5 + '\n' + Content_Type + '\n' +
                Date + '\n' + If_Modified_Since + '\n' + If_Match + '\n' +
                If_None_Match + '\n' + If_Unmodified_Since + '\n' + Range + '\n' +
                CanonicalizedHeaders + CanonicalizedResource)

# Generate the signature
signature = base64.b64encode(hmac.new(base64.b64decode(STORAGE_ACCOUNT_KEY), msg=STRING_TO_SIGN.encode('utf-8'), digestmod=hashlib.sha256).digest()).decode()

# Generate the authorization header
auth_header = f'SharedKey {STORAGE_ACCOUNT_NAME}:{signature}'


# Set the request URL
request_url = f'https://{STORAGE_ACCOUNT_NAME}.blob.core.windows.net/{CONTAINER_NAME}?restype=container'

# Set the request headers
request_headers = {
    'x-ms-date': REQUEST_DATE,
    'x-ms-version': REQUEST_VERSION,
    'Authorization': auth_header
}

# Send the request
response = requests.put(request_url, headers=request_headers)
print(response.content)
print(response.status_code)

结果:

enter image description here

关于python - Azure blob 共享 key 创建 403 错误获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75516194/

相关文章:

windows - 是否可以使用登录的 Windows 用户凭据对 Web API 进行身份验证?

python - 重新排序行值 csv pandas

python - 使用 python asyncio 执行多个任务

python - 为什么我的本地人没有在 rof 之外更新?

python - 在 python 中初始化 lambda 函数列表

c# - 有没有办法使用存储在同一容器中的公共(public)分区键对不同类型的文档进行事务查询/查找

azure - 如何使用 Terraform 为专用端点 azure 的网络接口(interface)添加标签?

python - 使用after_request时如何获取状态码?

python - 在 matplotlib 中绘制地转风图

python - 列名称的 sqlalchemy 别名也保留原始名称