【发布时间】:2016-05-21 12:39:25
【问题描述】:
我在 S3 中有一个与 CNAME 别名相关联的存储桶。我们现在假设域是 media.mycompany.com。存储桶中有所有设置为私有的图像文件。然而,它们在我的网站上使用 URL 签名公开使用。签名的 URL 可能如下所示:
这可以正常工作。我在 PHP 中使用 S3 帮助程序库来生成这样的 URL。这是该库的标识符:
$Id: S3.php 44 2008-12-23 15:38:38Z don.schonknecht $
我知道它很旧,但我依赖于这个库中的很多方法,所以升级并不是一件容易的事,而且正如所说,它对我来说效果很好。这是这个库中的相关方法:
public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false) {
$expires = time() + $lifetime;
$uri = str_replace('%2F', '/', rawurlencode($uri)); // URI should be encoded (thanks Sean O'Dea)
return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
$hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
urlencode(self::__getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
}
在我正常的工作设置中,我会这样调用这个方法:
$return = $this->s3->getAuthenticatedURL('media.mycompany.com', $dir . '/' . $filename,
$timestamp, true, false);
这将返回本文前面分享的正确签名的 URL,一切都很好。
但是,我现在想生成 HTTPS URL,这就是我遇到问题的地方。简单地将 HTTPs 添加到当前 URL(通过将方法的最后一个参数设置为 true)是行不通的,它会生成一个如下所示的 URL:
这显然行不通,因为我的 SSL 证书(由letsencrypt 创建)没有安装在亚马逊的域上,据我所知,没有办法这样做。
我了解了一种通过 SSL 访问存储桶的替代 URL 格式:
这显然适用于某些人,但不适用于我,据我所知,这是由于我的存储桶名称中有一个点 (.) 字符。我无法更改存储桶名称,这会对我的设置产生重大影响。
终于有了这样的格式:
在这里,我已经非常接近了。如果我采用一个有效的非安全 URL,并编辑该 URL 以采用这种格式,它就可以工作。显示图像。
现在我想让它通过我之前展示的签名方法以自动化方式工作。我这样称呼它:
$return = $this->s3->getAuthenticatedURL("s3.amazonaws.com/media.mycompany.com", $dir . '/' . $filename,
$timestamp, true, true);
这里的变化是替代的bucket名称格式,最后一个参数设置为true,表示HTTPS。这会导致这样的输出:
如您所见,它与我手动制作的 URL 具有相同的格式。但不幸的是,我遇到了签名错误:
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>
我不知道为什么这些签名不正确。我尝试将签名方法的第4个参数设置为true和false,但没有区别。
我错过了什么?
编辑
根据下面迈克尔的回答,我尝试在调用 S3 库后进行简单的字符串替换,这很有效。快速而肮脏的代码:
$return = $this->s3->getAuthenticatedURL("media.mycompany.com", $dir . '/' . $filename, $timestamp, true, true);
$return = substr_replace($return, "s3.amazonaws.com/", strpos($return, "media.mycompany.com"), 0);
【问题讨论】: