你的直觉在最重要的方面是正确的——这在任何有意义的意义上都不是“安全的”。
但它被击败的方式并不是你想象的那样。
当您单击网页上的链接,或者您的浏览器加载嵌入页面的图像时,您的浏览器会连接到 Web 服务器并发送请求。请求中包含 HTTP 标头,包括一个名为Referer:. 虽然并不总是存在(由于各种原因可能超出此答案的范围),但随附的值是您正在查看的页面的 URL - 在同一个浏览器选项卡中 - 当单击链接或图像时加载。
在 S3 中创建这样的策略通过字符串匹配这个值来实现访问控制,由浏览器提交,并且从安全角度来看几乎完全没有任何值。
因此,当您的页面打开时,另一个选项卡中的 Javascript 并不是真正的问题。令人担忧的是恶意用户使用伪造的标头制作请求- 使用( ) 或浏览器插件Referer:等测试工具很容易完成。现在桶说“哦,你在 example.com 的 Good Guy 页面上?这是你要的那个秘密图像文件。”curlcurl -v http://example-bucket.s3.amazonaws.com/secret-image.jpg -H 'Referer: http://example.com/good-guy.html'
那么有这么明显的限制,这个机制到底有什么用呢?
不保护您的内容。
但是,防止对您的内容进行广泛的热链接,将指向您的资产的链接嵌入到第三方站点中是有用的,这相当于窃取您的带宽。我曾经遇到过一个骗局网站,创建者在该网站上搜索了显示礼品卡图片的页面。他在我的一个网站上发现了这样的图像,但他没有下载它们……他将指向我的图像的链接嵌入到他的骗局 HTML 中。拒绝引用的配置显着减少了这种烦恼......但因为它适用于其他很少。
使用 S3,您可以动态生成签名 URL(假设您的站点是动态的)并将它们嵌入到 html 中。这可能是最有效的解决方案,因为您指定 URL 有效的时间段,并且这些 URL 不会被篡改到计算不可行的程度。CloudFront 与 S3 结合使用,允许您创建可实现类似结果的签名 cookie,但无需对您呈现的每个页面中的每个单独链接进行签名,而是使用 HTTPS 并通过 HTTPS 交付的具有非常短到期时间的对象的单独签名 URL与引用页面策略不同,它是一种有效的访问控制机制。