如何使用amazonsdk为虚荣域生成预先签名的AmazonS3 url
本文关键字:url AmazonS3 amazonsdk 何使用 虚荣 | 更新日期: 2023-09-27 18:26:52
我有一个名为foo.example.com的s3 bucket,它都是正确的CNAMEd。
我正在切换到最新的AWS.net SDK。
我希望生成预签名的url,如:
http://foo.example.com/myfile.txt?s3_params_here
注意虚荣的名字。
我有:
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);
我得到的网址是这样的:
http://foo.example.com.foo.example.com/myfile.txt?AWSAccessKeyId=bar&过期=1331069777&签名=234KoUUvfE1nCcs2vLj9RQUhqF8%3D
这显然是错误的。
我尝试了许多不同的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似乎很奇怪,但这对查询字符串身份验证没有影响,这与创建这些签名的方式一致,请参阅query string Request authentication Alternative,在这里您可以找到说明查询字符串请求身份验证方法的伪语法:
StringToSign = HTTP-VERB + "'n" +
Content-MD5 + "'n" +
Content-Type + "'n" +
Expires + "'n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
也就是说,域名根本不用于签名创建,而只是关于资源本身的信息;引用的伪语法片段正下方的示例查询字符串请求身份验证部分用实际资源说明了这一点。
评估
我不知道我们是否仍然存在误解,或者这是否只是AWS SDK for.NET中的一个错误,请参阅例如,当我设置包含"+"的响应标头覆盖时,为什么我的S3预签名请求无效?通过类似的解决方法解决了一个相关的错误,但同时已经修复;因此,这可能会升级到AWS论坛和/或支持渠道,以获得适当的答案或解决方案。
祝你好运!
想要的答案[功能失调]
S3 CNAME处理已经暗示了bucket名称,所以您所需要做的就是从GetPreSignedUrlRequest
中删除bucket名称
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
.WithKey(key)
.WithExpires(DateTime.Now.AddMinutes(5))
.WithProtocol(Protocol.HTTP);
我已经用我的一桶测试过了,它像预期的那样工作。
预签名URL在对请求进行签名之后返回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的末尾。
https://forums.aws.amazon.com/thread.jspa?threadID=70521