Azure 存储:如何避免 Blob 级别 SAS 令牌的时钟偏差问题

问题描述

我偶尔会遇到在服务器上生成的 Azure 存储 SAS 令牌的问题。我没有为开始时间设置任何内容,因为建议这样做以避免时钟偏差问题,并且我将到期时间设置为 DateTime.UtcNow 后 1 小时。有时,SAS 令牌不起作用,我猜这可能与时钟偏差问题有关。这是我最近收到的两个错误

<Error>
<Code>AuthenticationFailed</Code>
<Message>Server Failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:cb371f2b-801e-0063-16a1-08d06f000000 Time:2021-02-21T22:35:53.9832140Z</Message>
<AuthenticationErrorDetail>Signed expiry time [Sun,21 Feb 2021 20:39:40 GMT] must be after signed start time [Sun,21 Feb 2021 22:35:53 GMT]</AuthenticationErrorDetail>
</Error>

<Error>
<Code>AuthenticationFailed</Code>
<Message>Server Failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:8818c581-401e-0058-6477-08717d000000 Time:2021-02-21T17:35:37.1284611Z</Message>
<AuthenticationErrorDetail>Signature not valid in the specified time frame: Start [Sat,20 Feb 2021 00:15:01 GMT] - Expiry [Sat,20 Feb 2021 01:30:01 GMT] - Current [Sun,21 Feb 2021 17:35:37 GMT]</AuthenticationErrorDetail>
</Error>

这就是我生成令牌的方式:

var blobSasBuilder = new BlobSasBuilder
{
      BlobContainerName = containerName,BlobName = fileName,Resource = "b",ExpiresOn = DateTime.UtcNow.AddHours(1),Protocol = SasProtocol.Https
};

我该如何解决这个问题?根据上面的错误,貌似我是在token过期后尝试访问这个资源的,但实际上我是在token生成并发送给客户端后立即尝试访问的。正如我所说,这种情况并不经常发生,但它是一个反复出现的问题。

再想一想,我想知道这是否是 v12 SDK 的错误

解决方法

根据报错,开始时间晚于你的过期时间和当前时间。请将开始时间设置为至少过去 15 分钟。 enter image description here

例如

我使用 Net SDK Azure.Storage.Blobs

//  Creates a client to the BlobService using the connection string.
var blobServiceClient = new BlobServiceClient(storageConnectionString);

//  Gets a reference to the container.
var blobContainerClient = blobServiceClient.GetBlobContainerClient(<ContainerName>);

//  Gets a reference to the blob in the container
BlobClient blobClient = containerClient.GetBlobClient(<BlobName>);

//  Defines the resource being accessed and for how long the access is allowed.
var blobSasBuilder = new BlobSasBuilder
{
    StartsOn = DateTime.UtcNow.Subtract(-15),ExpiresOn = DateTime.UtcNow.AddHours(1),BlobContainerName = <ContainerName>,BlobName = <BlobName>,};
    
//  Defines the type of permission.
blobSasBuilder.SetPermissions(BlobSasPermissions.Write);
       
//  Builds an instance of StorageSharedKeyCredential      
var storageSharedKeyCredential = new StorageSharedKeyCredential(<AccountName>,<AccountKey>);

//  Builds the Sas URI.
var sasQueryParameters = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential);
,

生成 SAS 的代码必须在正确设置日期、时间和时区的机器上运行。

两种情况的错误消息略有不同。 第一个错误:是说签名到期时间是错误时间之前的~1h:56m,这怎么可能?也许 SAS 到期时间设置为过早的值,我的意思是几乎提前 2 小时而不是提前 15 分钟?或者 SAS 开始时间很可能大于 SAS 结束时间?

第二个错误:错误的时间是2月21日,但是SAS在2月20日到期,再次,看起来SAS时间已经到期,但这次是35小时以上而不是15分钟。

也许运行生成 SAS 的代码的机器在时间上有一些问题?这可以通过定期(例如每分钟一次)轮询该机器的时间并比较结果来检查。