I am following the official Azure documentation. My aim is to use Odata to do data queries for tables in Azure storage accounts. But the server always returns an error. I googled for a while. This seems to be related to the encryption of the request header. I am unable to resolve this issue. I would also appreciate any help.
import requests
import datetime
import hmac
import base64
from hashlib import sha256
account_name = '*****'
account_key = '*****'
table_name = '*****'
base_url = f'https://{account_name}.table.core.chinacloudapi.cn/{table_name}'
query_url = f"{base_url}()?$filter=PropertyName eq 'Value'"
now = datetime.datetime.utcnow()
date = now.strftime('%Y-%m-%d')
canonicalized_resource = f'/{account_name}/{table_name}'
string_to_sign = f'{date}\n{canonicalized_resource}'
signature = base64.b64encode(hmac.new(base64.b64decode(account_key), string_to_sign.encode('utf-8'), sha256).digest()).decode()
headers = {
'Accept': 'application/json;odata=nometadata',
'Content-Type': 'application/json',
'x-ms-date': date,
'Authorization': f'SharedKeyLite {account_name}:{signature}'
}
print(headers)
response = requests.get(query_url, headers=headers)
if response.status_code == 200:
result = response.json()
else:
print("", response.text)
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code>AuthenticationFailed</code>
<message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:fa58da7b-2002-0058-4c5e-953c35000000
Time:2023-06-02T14:26:40.7310444Z</message>
</error>
Process finished with exit code 0
Does the problem occur because the wrong method of calculating the account key causes the problem? Please make corrections to my code
Google. ChatGPT, none of them have a correct result.
To query the table from Azure table storage using REST API using Python. You can use the below code.
Code:
import requests
from hashlib import sha256
import base64
import hmac
import datetime
storageAccountName = '< Your storage account name>'
storageKey='< Your storage account key >'
filter_expression = "PartitionKey eq 'partitionkey1'"
filter1=f"?$filter={filter_expression}"
url = 'https://' + storageAccountName + '.table.core.windows.net/Employees()' + filter1
version = '2021-02-12' # x-ms-version
date = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") #x-ms-date
parameters = 'Employees()' #Mytablename
CanonicalizedResources = '/' + storageAccountName + '/' + parameters
CanonicalizedHeaders = 'x-ms-date:' + date
stringToSign = date + '\n' + CanonicalizedResources
signature = base64.b64encode(hmac.new(base64.b64decode(storageKey), stringToSign.encode('utf-8'), sha256).digest()).decode()
headers = {'x-ms-date': date,
'x-ms-version': version,
'Authorization': 'SharedKeyLite ' + storageAccountName + ':' + signature,
'Accept': 'application/json;odata=nometadata '}
# send the request
response = requests.get(url, headers=headers)
print (response)
print (response.headers)
print(response.text)
Output:
<Response [200]>
{'Cache-Control': 'no-cache', 'Transfer-Encoding': 'chunked', 'Content-Type': 'application/json;odata=nometadata;streaming=true;charset=utf-8', 'Server': 'Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0', 'x-ms-request-id': 'xxxxxxxxx', 'x-ms-version': '2021-02-12', 'X-Content-Type-Options': 'nosniff', 'Date': 'Mon, 05 Jun 2023 06:39:19 GMT'}
{"value":[{"PartitionKey":"partitionkey1","RowKey":"rowkey1","Timestamp":"2023-03-16T11:12:28.2723247Z"}]}
Reference: Querying tables and entities (REST API) - Azure Storage | Microsoft Learn