Я хотел создать контейнер больших двоичных объектов Azure, используя код Python, используя авторизацию общего ключа,
Я получаю ошибку ниже:
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)
приведенный выше код использует авторизацию общего ключа для выполнения запроса, мы должны заменить ключ доступа и учетную запись хранения для проверки порядка
Текущий ответ: 403 Ожидаемый ответ: 201
@GauravMantri, да, наш поставщик хранилища использует авторизацию с общим ключом, которую мы устанавливаем для кеша nginx, однако они получают ответ 409, поэтому я хотел пока изолировать nginx, сделать прямой вызов хранилища и попробовать аналогичные команды, которые использует наш поставщик хранилища.
Спасибо. Вы пытаетесь создать контейнер больших двоичных объектов в своем коде, верно?
@GauravMantri да создание контейнера
Я полагаю, что причина, по которой вы получаете эту ошибку, заключается в том, что вы устанавливаете значение Content-Length
на 0
в STRING_TO_SIGN
, однако сервер использует пустую строку при проверке подписи (пожалуйста, просмотрите сведения об ошибке, в которых указана строка для подписи, используемая сервером для проверить подпись).
Из этой ссылки:
Пожалуйста, попробуйте установить переменную Content_Length
в пустую строку вместо 0
.
В дополнение к тому, что сказал @Gaurav Mantri, вы получаете это из-за того, что заголовки авторизации сформированы неправильно. После воспроизведения с моей стороны это работало нормально, когда я заменял Date
и Content 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)
Полученные результаты:
форматирование вашего кода может быть проблемой, это полностью вставленный ответ кода
@sagar, вы инициализировали дату переменной как Date = REQUEST_DATE
. И при создании string_to_sign это вызывает проблему. Я использовал Date=''
и получил желаемые результаты. Вы можете использовать приведенный выше код, в котором я заменил дату и длину содержимого пустой строкой, чтобы успешно создать контейнер.
@swathi, не уверен, что я все еще получаю ту же ошибку, обновленный код, какая-либо ошибка конфигурации, например, запрет на использование общего ключа в моем хранилище?
@sagar Это из-за версии запроса, которую вы упомянули в своем коде. Решение относится к первому обновлению, о котором вы упомянули, то есть REQUEST_VERSION = '2020-04-08'
. Глядя на ваше недавнее редактирование, я вижу, что вы изменили его на «2014-02-14». Попробуйте изменить версию на 2020-04-08 или, если вы пытаетесь использовать «2014-02-14», посмотрите документ, предоставленный @Gaurav Mantri, и соответствующим образом сформируйте String_to_sign.
@swathi, я изменил версию на тот же результат
@sagar, я обновил код, теперь попробуйте скопировать и вставить тот же код, заменив его своим контейнером и ключом доступа.
Давайте продолжим обсуждение в чате.
это работает для другой учетной записи, однако теперь я получаю другую ошибку для существующей, но я должен принять этот ответ python3 test.py b'\xef\xbb\xbf<?xml version = "1.0" encoding = "utf-8"? ><Error><Code>AuthorizationFailure</Code><Message>Этот запрос не авторизован для выполнения этой операции.\nRequestId:77440ab1-e01e-000f-7ce0-459e3e000000\nTime:2023-02-21T10: 35:09.1160088Z</Message></Error>' 403
@sagar, судя по вашему сообщению об ошибке This request is not authorized to perform this operation
, у вас может не хватить прав для создания контейнера в целевой учетной записи хранения.
@swathi, для включения всей сети в разделе сети, это сработало, большое спасибо за вашу помощь.
Есть ли причина, по которой вы не используете Storage SDK для Python?