如何使用 amazon sdk 为虚域生成预签名的 Amazon S3 url?

Nik*_*Nik 5 .net c# amazon-s3

我有一个名为 foo.example.com 的 s3 存储桶,它的所有 CNAME 都正确。

我正在切换到最新的 AWS .net SDK。

我希望生成预签名的 url,如:

http://foo.example.com/myfile.txt?s3_params_here

注意那里的虚荣cname。

我有:

string bucketName = "foo.example.com";

AmazonS3Client s3Client = new AmazonS3Client("bar", "xxx",
    new AmazonS3Config
    {
        ServiceURL = bucketName, 
        CommunicationProtocol = Protocol.HTTP
    });


string key = "myfile.txt";


GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
.WithBucketName(bucketName)
.WithKey(key)
.WithExpires(DateTime.Now.AddMinutes(5))
.WithProtocol(Protocol.HTTP);

string url = s3Client.GetPreSignedURL(request);
Run Code Online (Sandbox Code Playgroud)

我得到的网址是这样的:

http://foo.example.com.foo.example.com/myfile.txt?AWSAccessKeyId=bar&Expires=1331069777&Signature=234KoUUvfE1nCcs2vLj9RQUhqF8%3D

这显然是错误的。

我已经尝试了许多不同的 ServiceURL、bucketname 等变体,但似乎没有任何效果。

我找不到任何好的文档 - 这样做的正确方法是什么?

谢谢。

Ste*_*pel 4

更新[解决方法]

\n

与此同时,我解决了我的相互矛盾的测试结果,这些结果分别源于不系统的测试和 URL 操作。以下解决方法对我来说很有效(即经过测试且可重现),只需从您的解决方案开始:

\n
string bucketName = "foo.example.com";\n\n// [...]\n\nGetPreSignedUrlRequest request = new GetPreSignedUrlRequest()\n    .WithBucketName(bucketName)\n    .WithKey(key)\n    .WithExpires(DateTime.Now.AddMinutes(32))\n    .WithProtocol(Protocol.HTTP);\n
Run Code Online (Sandbox Code Playgroud)\n

现在这会产生带有重复域名的错误 URL,即http://foo.example.com.foo.example.com/myfile.txt?[...]

\n

不过,可以简单地删除重复项,例如:

\n
string url = s3Client.GetPreSignedURL(request);\n\n// KLUDGE: remove duplicate domain name.\nurl = url.Replace(bucketName + "." + bucketName, bucketName);\n
Run Code Online (Sandbox Code Playgroud)\n

http://foo.example.com/myfile.txt?[...]通过解决下面概述的所需方法所遇到的限制,这为我(即)生成了一个正确的工作预签名 URL 。

\n

理由

\n

像这样操作生成的 URL 似乎很奇怪,但这对查询字符串身份验证没有影响,这与这些签名的创建方式是一致的,请参阅查询字符串请求身份验证替代方案,您将在其中找到说明以下内容的伪语法:查询字符串请求认证方法

\n
StringToSign = HTTP-VERB + "\\n" +\n    Content-MD5 + "\\n" +\n    Content-Type + "\\n" +\n    Expires + "\\n" +\n    CanonicalizedAmzHeaders +\n    CanonicalizedResource;    \n
Run Code Online (Sandbox Code Playgroud)\n

也就是说,域名根本不用于签名创建,而仅用于有关资源本身的信息;引用的伪语法片段正下方的示例查询字符串请求身份验证部分用实际资源说明了这一点。

\n

评估

\n

我不知道我们是否仍然存在误解,或者这是否可能只是AWS SDK for .NET中的错误,请参阅例如为什么当我设置响应标头覆盖时我的 S3 预签名请求无效包含 \xe2\x80\x9c+\xe2\x80\x9d?也通过类似的解决方法解决了相关错误,但同时已修复;因此,这可能会升级到 AWS 论坛和/或支持渠道以获得适当的答案或解决方案。

\n

祝你好运!

\n
\n

所需答案[功能失调]

\n

S3 CNAME 处理已经暗示了存储桶名称,因此您需要做的就是从 中删除存储桶名称GetPreSignedUrlRequest,即它应该如下所示:

\n
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()\n    .WithKey(key)\n    .WithExpires(DateTime.Now.AddMinutes(5))\n    .WithProtocol(Protocol.HTTP);\n
Run Code Online (Sandbox Code Playgroud)\n

我已经用我的一桶测试过它,它的工作原理就像预期的那样。

\n