S3 请求时间太偏斜

S3 Request time too skewed

我目前正在用 C# 构建一个应用程序,它使用 AWS SDK 将文件上传到 S3。

但是,我有一些用户在应用程序尝试上传文件时遇到 "Request time too skewed" 错误。

我知道问题是用户的时钟不同步,但是,很难指望用户更改它,所以我想知道,有什么办法可以让这个错误不发生(任何使用 NTP 或类似工具获取准确时间的 .NET 功能?)

下面是我用来上传文件的当前代码。

var _s3Config = new AmazonS3Config { ServiceURL = "https://s3-eu-west-1.amazonaws.com" };
var _awsCredentials = new SessionAWSCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.SessionToken);
var s3Client = new AmazonS3Client(_awsCredentials, _s3Config);
var putRequest = new PutObjectRequest
{
  BucketName = "my.bucket.name",
  Key = "/path/to/file.txt",
  FilePath = "/path/to/local/file.txt"
};
putRequest.StreamTransferProgress += OnUploadProgress;
var response = await s3Client.PutObjectAsync(putRequest);

从时间服务器获取时间实际上是您挑战中比较容易的部分。据我所知,没有 built-in 从时间服务器获取准确时间的 C# 功能,但快速搜索会为 NTP 客户端生成大量示例代码。我在 dotnet-snippets.com 找到了一个很好的综合示例(对你的情况来说可能有点矫枉过正),并且在标题为“How to Query an NTP Server using C#?[的页面中的 Stack Overflow 上找到了一个非常精简的版本。 =32=]”。后者看起来对你的情况可能有效,因为你所需要的只是对当前时间的一个相当准确的想法。

现在开始真正的挑战:将这段时间用于 Amazon S3。首先,介绍一些背景知识,因为理解为什么会发生这种情况很重要。时间偏差限制旨在防止重放攻击,如下所述: http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

正因如此,亚马逊在构造HTTP(S)请求时,将当前时间戳内置到AWS SDK中使用的身份验证签名中。但是,SDK 始终使用当前时间(无法在 SDK 方法中覆盖它): https://github.com/aws/aws-sdk-net/blob/master/AWSSDK_DotNet35/Amazon.Runtime/Internal/Auth/AWS3Signer.cs#L119

请注意,在所有情况下,SDK 使用 AWSSDKUtils.FormattedCurrentTimestampRFC822 作为时间戳,调用者无法将不同的值传递给方法。

所以这给你留下了两个我可以看到的选项:

  1. 绕过 Amazon SDK 并使用从 NTP 服务器检索的时间构建您自己的 HTTP 请求。这是可行的,但并不容易。 Amazon 不鼓励这种方法,因为 SDK 提供了很多有用的包装器来确保你正确地使用 API 作为一个整体,处理大量你必须自己做的繁琐的消息处理,如果你直接使用 HTTP .它还有助于处理大量错误并确保在传输中断时正确清理。

  2. 克隆 Amazon SDK git 存储库并创建您自己的分支并进行修改以允许您传入当前时间。这也很困难,因为您必须想出一种方法将时间传递到 API objects 的几层。而且您将失去能够在新 SDK 可用时轻松更新到新 SDK 的好处。

抱歉,没有简单的答案,但希望对您有所帮助。

如果您问这个问题,您可能已经使用提供的代码示例尽可能地了解 AWS。

我发现 AWS 提供的大多数异步上传功能都更偏理论,或者更适合有限的用例,而不是为主流产品做好准备——尤其是使用所有这些浏览器和操作系统的最终用户: )

我建议重新考虑您的程序设计:创建您自己的 C# 上传转门并将 AWS SDK 上传功能 运行 保留为后台进程(或系统管理功能),以便 AWS 服务器仅处理您的服务器的时间。