C# 如何使用AmazonSDK为虚荣域生成预先签名的AmazonS3URL?

C# 如何使用AmazonSDK为虚荣域生成预先签名的AmazonS3URL?,c#,.net,amazon-s3,C#,.net,Amazon S3,我有一个名为foo.example.com的s3 bucket,它的命名都是正确的 我正在切换到最新的AWS.NETSDK 我希望生成预签名url,如: 注意这里的虚荣名称 我有: string bucketName = "foo.example.com"; AmazonS3Client s3Client = new AmazonS3Client("bar", "xxx", new AmazonS3Config { ServiceURL = bucketNam

我有一个名为foo.example.com的s3 bucket,它的命名都是正确的

我正在切换到最新的AWS.NETSDK

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

注意这里的虚荣名称

我有:

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);
我得到的url类似于:

这显然是错误的

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

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

谢谢

更新[解决方法] 我同时解决了我的自相矛盾的测试结果,它们分别来自于非系统测试和URL操作。以下解决方法对我来说很有用(即经过测试且可复制),只需从您的解决方案开始:

string bucketName = "foo.example.com";

// [...]

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
    .WithBucketName(bucketName)
    .WithKey(key)
    .WithExpires(DateTime.Now.AddMinutes(32))
    .WithProtocol(Protocol.HTTP);
现在,这会产生一个重复域名的错误URL,即
http://foo.example.com.foo.example.com/myfile.txt?[…]

但可以简单地删除副本,例如:

string url = s3Client.GetPreSignedURL(request);

// KLUDGE: remove duplicate domain name.
url = url.Replace(bucketName + "." + bucketName, bucketName);
这将为我生成一个正确的工作预签名URL(即
http://foo.example.com/myfile.txt?[…]
)通过解决所遇到的与下面概述的所需方法有关的限制

正当理由 像这样操纵生成的URL似乎有些奇怪,但这对查询字符串身份验证没有影响,这与创建这些签名的方式一致,请参见,您将在其中找到说明查询字符串请求身份验证方法的伪语法:

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

评估 我不知道我们是否仍然存在误解,或者这可能只是中的一个错误,请参阅,例如,通过类似的解决方法解决的相关错误,同时已修复;因此,这可能会升级到AWS论坛和/或支持渠道,以获得适当的答案或解决方案

祝你好运


期望答案[功能失调] S3 CNAME处理已经暗示了bucket名称,因此您需要做的就是从
GetPreSignedUrlRequest
中删除您的bucket名称,即它应该是这样的:

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
    .WithKey(key)
    .WithExpires(DateTime.Now.AddMinutes(5))
    .WithProtocol(Protocol.HTTP);
我已经用我的一个水桶测试过了,它像预期的那样工作

presignedURL在对请求签名后返回URL对象。我使用了相同的>没有实际问题,但有一些事情需要考虑:

  • 确保您正在考虑的对象URL没有“/”,如果>以“/”开头存储路径,则很容易发生这种情况,您可能会将对象存储在某个>之类的路径中https:///x/y/z/abc.png 这种资源的关键是x/y/z/abc.png>而不是/x/y/z/abc.png

  • 如果上述条件得到保证,那么从返回的URL对象中,从URL对象URL获取查询参数>。getQuery()将返回包含>签名信息的查询参数,只需将其添加到原始awsURL的后缀,就可以解决>的编码问题

  • 希望这有帮助

    本质上,您需要对返回的url对象使用url.getQuery,而不是简单地将其附加到bucket的末尾


    你好,斯蒂芬。非常感谢,但是我没有看到上面指定了自定义域的位置,以便S3 CNAME可以暗示它?我们在这里设置的只是一把钥匙。谢谢。@Nik:你完全正确,当然,我把本地测试收集的信息和我最初的错误答案弄乱了(我意识到它没有解决这个问题后,无意中删除了它;)-抱歉,麻烦了!
    ServiceURL
    确实必须是您的CNAME,删除已经隐含的bucket名称会处理重复。当我删除WithBucketName()时,我发现域是正确的,但由于某种原因,url中没有使用密钥。e、 g.:。你能确认这对你来说确实有效吗?@Nik:我又试了一次,至少找到了一个解决办法,这次测试并端到端复制了;)谢谢你的坚持,Steffen-很有效!在我看来,这似乎是AWS SDK中的一个错误。我刚刚第二次删除了我的答案(永久删除),并将避免添加另一个答案,直到我可以在.NET中实际复制端到端解决方案。自定义域的预签名URL原则上是可以工作的(例如,请参阅这个古老的AWS团队对的响应,我也相应地使用了它们;Ruby示例中的VALITY参数已被弃用,并且在AWS SDK for.NET中不可用,在那里它应该是这样工作的,AFAIK-再次为麻烦道歉!这个链接与编码问题有关。您能更清楚地了解它是如何工作的吗解决我的问题?谢谢!
    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
        .WithKey(key)
        .WithExpires(DateTime.Now.AddMinutes(5))
        .WithProtocol(Protocol.HTTP);