我正在使用适用于 PHP 的 AWS 开发工具包向 S3 存储桶上传和显示文件。
这些文件只能通过我的网站访问,不允许其他引荐来源 - 没有热链接等。
我还需要能够复制存储桶中的对象。
我像往常一样创建和连接:
$s3Client = new AwsS3S3Client([
'version' => 'latest',
'region' => 'eu-west-2'
]);
$s3 = $s3Client::factory(array(
'version' => 'latest',
'region' => 'eu-west-2',
'credentials' => array(
'provider' => $provider,
'key' => $key,
'secret' => $secret
)
));
并执行复制对象命令:
$s3->copyObject([
'Bucket' => "{$targetBucket}",
'Key' => "{$targetKeyname}",
'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
]);
我尝试了使用"如果字符串像引荐来源网址一样允许"的策略,但 AWS 随后告诉我我允许公共访问?!?!? 一切正常,即使是 copyObject 操作,但文件仍然可以直接从任何地方访问!
我尝试使用"如果字符串不像引用器,则拒绝",它主要按预期工作 - 我可以上传和显示文件,文件在直接链接时不显示(这是我想要的) - 但是,copyObject 操作不再有效,我收到访问被拒绝错误。
我已经尝试了我能想到的其他一切,并花了几个小时在谷歌上搜索和寻找答案,但无济于事。
以下是每个单独的策略...
仅允许文件访问 (GetObject) 如果字符串类似引用:
{
"Version": "2008-10-17",
"Id": "",
"Statement": [
{
"Sid": "Deny access if referer is not my site",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::MY-BUCKET/*"
],
"Condition": {
"StringLike": {
"aws:Referer": [
"http://MY-SITE/*",
"https://MY-SITE/*"
]
}
}
}
]
}
结果:上传和复制对象有效,但文件仍然可以在任何地方访问
拒绝所有操作 (*) 如果字符串不像引用:
{
"Version": "2008-10-17",
"Id": "",
"Statement": [
{
"Sid": "Deny access if referer is not my site",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::MY-BUCKET/*"
],
"Condition": {
"StringNotLike": {
"aws:Referer": [
"http://MY-SITE/*",
"https://MY-SITE/*"
]
}
}
}
]
}
结果:复制对象操作不再有效,我收到拒绝访问错误
AWS可能会警告您它是公开的,因为出于所有实际目的,它仍然是公开的。
警告
应谨慎使用此密钥:
aws:referer
允许 Amazon S3 存储桶拥有者帮助防止未经授权的第三方站点将其内容提供给标准 Web 浏览器。[...]由于aws:referer
值由调用方在 HTTP 标头中提供,因此未经授权的各方可以使用修改或自定义的浏览器来提供他们选择的任何 aws:referer 值。因此,不应使用 aws:referer 来防止未经授权的各方发出直接的 AWS 请求。它仅用于允许客户保护存储在 Amazon S3 中的数字内容,使其不被未经授权的第三方站点引用。https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
如果您对这种原始机制感到满意,请使用它,但请注意,它所做的只是信任浏览器所做的声明。
这就是你的copyObject()
问题 - 请求不是由浏览器发出的,因此没有Referer
标头进行验证。
您可以使用StringLikeIfExists
条件测试来仅Deny
错误的引用器(忽略缺少引用器,就像对象副本一样)或者 - 更好的是 - 只需授予s3:GetObject
StringLike
您的引用,了解公共警告是正确的 - 这允许未经身份验证的访问,这就是引用检查的意义。 您的内容仍然可以公开访问,但如果从其他站点热链接,则不能从标准的、未经修改的 Web 浏览器访问。
为了提高安全性,您需要使用 S3 资产的预签名 URL(过期时间短)呈现 HTML,或者使用 Amazon Cognito 进行全面和适当的授权。
默认情况下,Amazon S3 中的对象是私有的。除非以某种方式授予访问权限(例如,在 IAM 用户、IAM 组或 S3 存储桶策略上),否则没有访问权限。
上述策略都是拒绝策略,可以覆盖允许策略。因此,它们不是某些东西可以访问的原因。
应首先发现授予访问权限的内容,然后删除该访问权限。对象再次私有后,您应该创建一个存储桶策略,其中包含Allow
语句,这些语句定义在什么情况下允许访问。