Authenti" />

【Azure 存储服务】记一次调用Storage Blob API使用 SharedKey Authorization出现的403错误

Authorization,SharedKey,API,存储 · 浏览次数 : 24

小编点评

## 代码分析 您的问题是 Azure Storage Blob REST API上传文件时,使用 SharedKey 进行认证出现 403 错误,错误消息提示请求的 Authorization header 中的 SharedKey 和 Blob 服务端 SharedKey 信息不一致。 **问题原因:** 1. 在代码中获取 x-ms-date 时,两次调用 get_date() 方法获取时间,导致时间不一致。 2. SharedKey 和 Blob 服务端 SharedKey 信息可能使用不同的格式或内容,导致验证失败。 **解决方案:** 1. 将代码中的两个 get_date() 方法合并成一个,只调用一次并使用同一个时间值。 2. 确保 SharedKey 和 Blob 服务端 SharedKey 信息使用相同的格式,例如都使用 Base64编码。 3. 仔细调试 SharedKey 和 Blob 服务端 SharedKey 信息的格式和内容,确保它们一致。 **修改后的代码片段:** ```python def get_date(): # 获取最初的时间值 ms_date = get_date_from_storage_account() # 合并两个 get_date() 方法 return ms_date ``` **附录:** * 参考文档介绍如何使用 AAD 和 Storage Account Access Key 进行认证获取 Blob 的 Python 代码。 * 请参考 Azure Storage Blob 存储和 Python 入门教程获取更多帮助。

正文

问题描述

使用Azure Storag Blob REST API上传文件,用SharedKey作为Authorization出现403错误。

错误消息

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:7df1f139-901e-0063-64eb-4be2dc000000\nTime:2023-03-01T03:08:27.3277224Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request \’*\' is not the same as any computed signature. Server used following string to sign: \'PUT\n\n\n19122\n\ntext/plain; charset=UTF-8\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:Wed, 01 Mar 2023 03:08:26 GMT\nx-ms-version:2015-02-21\n/adlstestaccount/blobtest/20230220065800824-2696.jpg\'.</AuthenticationErrorDetail></Error>' reason=Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

 

问题发现

在错误消息“Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.”中,提到了请求SharedKey 中的内容和请求Header中的内容不一致。 

检查生成SharedKey 的代码

第一步:生成put_str 

put_str = u"PUT\n\n\n{}\n\n{}; charset={}\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:{}\nx-ms-version:{}\n/{}/{}/{}".format(str(len(file)),
'text/plain' ,
'UTF-8',
get_date(),
'2015-02-21',
'<your storage account name>',
'<container name>',
file_name) sig_str
= base64.b64encode(hmac.new(account_key_decoded, put_str, digestmod=hashlib.sha256).digest()).decode('utf-8')

第二步:请求的Header中,通过Authorization 传递 sig_str

        headers = {
            "x-ms-blob-type": "BlockBlob",
            "x-ms-date": get_date(),
            "x-ms-version": "2015-02-21",
            "Authorization": "SharedKey {}:{}".format("adlstestaccount", sig_str),
            "Content-Type": "{}; charset={}".format('text/plain', 'UTF-8'),
            "Content-Length": str(len(file))
        }

在调试代码的过程中,对比 put_str 内容和 blob服务端 SharedKey信息,发现它们的 x-ms-date 部分值不一样:

因SharedKey不一样,所以认证时候出现403 Server failed to authenticate the request. 

在第一步生成 put_str 的时候获取 x-ms-date 的时候调用的 get_date() 获取时间,第二步在生成Header x-ms-date的时候再一次调用 get_date() 获取时间,由于代码在执行时候出现了时间差,这就导致了header中的时间和Authorization SharedKey中时间不一致。这就是出现403的根本原因。

 

解决办法就是在获取x-ms-date的时候,不要两次调用get_date()方法,而是只调用一次,然后put_str和header中都使用同一个时间值。

修改后的代码片段为

//获取时间
ms_date = get_date();

put_str = u"PUT\n\n\n{}\n\n{}; charset={}\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:{}\nx-ms-version:{}\n/{}/{}/{}".format(str(len(file)),
'text/plain' ,
'UTF-8',
ms_date,
'2015-02-21',
'<your storage account name>',
'<container name>',
file_name)

sig_str = base64.b64encode(hmac.new(account_key_decoded, put_str, digestmod=hashlib.sha256).digest()).decode('utf-8')


headers = {
            "x-ms-blob-type": "BlockBlob",
            "x-ms-date": ms_date,
            "x-ms-version": "2015-02-21",
            "Authorization": "SharedKey {}:{}".format("adlstestaccount", sig_str),
            "Content-Type": "{}; charset={}".format('text/plain', 'UTF-8'),
            "Content-Length": str(len(file))
        }
        

 

附录:使用AAD 和 Storage Account Access Key进行认证获取Blob的Python实例代码

from azure.storage.filedatalake import DataLakeServiceClient
from azure.identity import ClientSecretCredential
from azure.identity import AzureAuthorityHosts

tenant_id = "*"
client_id = "*"
client_secret = "*"
authority = AzureAuthorityHosts.AZURE_CHINA 
credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret,authority=authority) 
account_url = "*"
account_key = "*"
container="*"
folder="*"
connection_string = "*"

def initialize_storage_account():
    try:
        global service_client 
        #使用AAD 认证
        #service_client = DataLakeServiceClient(account_url=account_url, credential=credential)

        #使用Access Key认证
        service_client = DataLakeServiceClient.from_connection_string(connection_string)
    except Exception as e:
         print(e)
         

def list_directory_contents():
    try:
        file_system_client = service_client.get_file_system_client(file_system=container)
        paths = file_system_client.get_paths(path=folder)
        for path in paths:
         print(path.name + '\n')
    except Exception as e:
     print(e)

initialize_storage_account()
list_directory_contents()
    

 

 

 

参考资料

通过共享密钥进行授权 : https://learn.microsoft.com/zh-cn/rest/api/storageservices/authorize-with-shared-key 

Azure Blob 存储和 Python 入门 : https://learn.microsoft.com/zh-cn/azure/storage/blobs/storage-blob-python-get-started?tabs=azure-ad

 

与【Azure 存储服务】记一次调用Storage Blob API使用 SharedKey Authorization出现的403错误相似的内容:

【Azure 存储服务】记一次调用Storage Blob API使用 SharedKey Authorization出现的403错误

问题描述 使用Azure Storag Blob REST API上传文件,用SharedKey作为Authorization出现403错误。 错误消息 b'\xef\xbb\xbfAuthenti

【Azure 存储服务】存储在Azure Storage Table中的数据,如何按照条件进行删除呢?

问题描述 如何按条件删除 Storage Table 中的数据,如果Table中有大量的条记录需要删除,Java代码如何按条件删除 Table中的数据(Entity)? (通过Azure Storage Explorer工具是可以删除,但是由于数据量太大,人工操作耗时太久,所以需要使用Java代码完

【Azure 存储服务】Azure Blob Storage SDK 升级失败,遇见 Unsatisfied Dependency Exception 和 Unexpected Length Exception

问题描述 在升级Java Azure Blob Storage SDK的过程中,先后遇见了 UnsatisfiedDependencyException 和 UnexpectedLengthException. 错误一:Org.springframework.beans.factory Unsati

【Azure 存储服务】多设备并发往 Azure Storage Blob 的 Container 存数据是否可以

问题描述 多设备并发往 Azure Storage Blob 的 Container 存数据是否可以? 问题解答 可以! Azure Storage 是支持的并发存储数据的,Blob 可以使用乐观并发或悲观并发模型的,具体实现可以参考文档:https://docs.microsoft.com/zh-

【Azure 存储服务】Azure Data Lake Storage (ADLS) Gen2 GRS Failover是否支持自动切换或者手动切换到灾备的终结点呢?

问题描述 在Azure的存储服务中,介绍灾备恢复和Storage Account故障转移的文档中,有一句话“Account failover is not supported for storage accounts with a hierarchical namespace enabled.” 而

【Azure 存储服务】如何查看Storage Account的删除记录,有没有接口可以下载近1天删除的Blob文件信息呢?

问题描述 如何查看Storage Account的删除记录,有没有接口可以下载近1天删除的Blob文件信息呢?因为有时候出现误操作删除了某些Blob文件,想通过查看删除日志来定位被删除的文件信息。 问题解答 如果没有启用Storage Account的软删除功能,则没有办法直接查看近期有删除的Blo

【Azure 存储服务】MP4视频放在Azure的Blob里面,用生成URL在浏览器中打开之后,视频可以正常播放却无法拖拽视频的进度

问题描述 把MP4视频放在Azure的Blob里面,用生成URL在浏览器中打开之后,视频可以正常播放却无法拖拽视频的进度,这是什么情况呢? 问题解答 因为MP4上传到Azure Blob后,根据公开的权限,可以直接通过Storage Blob URL +/ Blob Container + / Bl

【Azure 存储服务】Azure Storage Account Queue中因数据格式无法处理而在一个小时内不在可见的问题

问题描述 在从Storage Account 队列中获取数据(Queue),在门户中,明显看见有数据,但是通过消费端代码去获取的时候,就是无法获取到有效数据的情况。获取消息的代码如下: 问题解答 经过对 receiveMessages 方法定义的查询,第二个参数,第三个参数的两个时间表示的意思为 消

【Azure 存储服务】.NET7.0 示例代码之上传大文件到Azure Storage Blob (一)

问题描述 在使用Azure的存储服务时候,如果上传的文件大于了100MB, 1GB的情况下,如何上传呢? 问题解答 使用Azure存储服务时,如果要上传文件到Azure Blob,有很多种工具可以实现。如:Azure 门户, Azure Storage Explorer, 命令行工具 az copy

【Azure 存储服务】.NET7.0 示例代码之上传大文件到Azure Storage Blob (二)

问题描述 在上一篇博文(【Azure 存储服务】.NET7.0 示例代码之上传大文件到Azure Storage Blob (一):https://www.cnblogs.com/lulight/p/17061631.html)中,介绍了第一种分片的方式上传文件。 本文章接着介绍第二种方式,使用 M