根据引用者限制对AWS S3存储桶的访问

2023-11-26

我试图限制对 S3 存储桶的访问,并仅允许基于引用来源的列表中的某些域。

存储桶策略基本上是:

{
"Version": "2012-10-17",
"Id": "http referer domain lock",
"Statement": [
    {
        "Sid": "Allow get requests originating from specific domains",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::example.com/*",
        "Condition": {
            "StringLike": {
                "aws:Referer":  [ 
                    "*othersite1.com/*",
                    "*othersite2.com/*",
                    "*othersite3.com/*"
                ]
            }
        }
    }
 ]
}

othersite1、2 和 3 调用我存储在域 example.com 下的 s3 存储桶中的对象。 我还有一个附加到存储桶的 Cloudfront 发行版。我在字符串条件之前和之后使用 * 通配符。引荐来源网址可以是 othersite1.com/folder/another-folder/page.html。引用者也可以使用 http 或 https。

我不知道为什么会收到 403 Forbidden 错误。

我这样做主要是因为我不希望其他网站调用该对象。

任何帮助将不胜感激。


作为正确缓存行为所必需的,CloudFront 在将请求转发到源服务器之前会剥离请求中的几乎所有请求标头。

Referer| CloudFront 删除标头。

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-headers-behavior

因此,如果您的存储桶尝试根据引用页面阻止请求(有时会这样做以防止热链接),则默认情况下,S3 将无法看到Referer标头,因为 CloudFront 不会转发它。

而且,这是一个很好的例证whyCloudFront 不会转发它。如果 CloudFront 转发标头,然后盲目缓存结果,则存储桶策略是否具有预期效果将取决于第一个请求是来自预期站点之一还是来自其他地方 - 并且其他请求者将获得缓存的响应,这可能是wrong回复。

(tl;dr) 将其列入白名单Referer用于转发到源的标头(在 CloudFront 缓存行为设置中)解决了此问题。

但是,有一个问题。

现在您正在转发Referer标头到 S3,您已经扩展了缓存键-- CloudFront 缓存响应的事物列表 -- 包括Referer header.

因此,现在,对于每个对象,CloudFront 将不会提供来自缓存的响应,除非传入请求的Referer标头匹配exactly来自已缓存请求的一个...否则该请求必须发送到 S3。而且,关于引用标头的事情是引用page,不是指代site,所以每个page来自授权站点的这些资产将在 CloudFront 中拥有自己的缓存副本。

这本身并不是问题。这些额外的对象副本是免费的,这就是 CloudFront 的设计工作方式...问题是,它降低了给定对象位于给定边缘缓存中的可能性,因为每个对象必然会被引用较少。如果您的流量很大,那么这一点就变得不那么重要,甚至可以忽略不计;如果您的流量较小,那么这一点就变得更重要。更少的缓存命中意味着更慢的页面加载和更多的请求发送到 S3。

对于这是否适合您没有正确的答案,因为它非常具体于您使用 CloudFront 和 S3 的方式。

但是,这是另一种选择:

您可以删除Referer通过将 CloudFront 配置为触发一个标头白名单中的标头转发到 S3 并消除对缓存命中产生负面影响的可能性Lambda@Edge 查看器请求触发器它将检查来自前门的每个请求,并阻止那些不是来自您希望允许的引用页面的请求。

查看器请求触发器在特定缓存行为匹配之后、检查实际缓存之前触发,并且大多数传入标头仍然完好无损。您可以允许请求继续进行(可以选择进行修改),也可以生成响应并取消其余的 CloudFront 处理。这就是我在下面要说明的——如果主机部分Refererheader 不在可接受值数组中,我们生成 403 响应;否则,请求将继续,检查缓存,并且仅根据需要查询源。

触发此触发器会给每个请求增加少量开销,但该开销可能会比降低缓存命中率更理想。因此,以下不是“更好”的解决方案——只是一个替代解决方案。

这是用 Node.js 6.10 编写的 Lambda 函数。

'use strict';

const allow_empty_referer = true;

const allowed_referers = ['example.com', 'example.net'];

exports.handler = (event, context, callback) => {

    // extract the original request, and the headers from the request
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    // find the first referer header if present, and extract its value;
    // then take http[s]://<--this-part-->/only/not/the/path.
    // the || [])[0]) || {'value' : ''} construct is optimizing away some if(){ if(){ if(){ } } } validation

    const referer_host = (((headers.referer || [])[0]) || {'value' : ''})['value'].split('/')[2];

    // compare to the list, and immediately allow the request to proceed through CloudFront 
    // if we find a match

    for(var i = allowed_referers.length; i--;)
    {
        if(referer_host == allowed_referers[i])
        {
            return callback(null,request);
        }
    }

    // also test for no referer header value if we allowed that, above
    // usually, you do want to allow this

    if(allow_empty_referer && referer_host === "")
    {
        return callback(null,request);
    }

    // we did not find a reason to allow the request, so we deny it.

    const response = {
        status: '403',
        statusDescription: 'Forbidden',
        headers: {
            'vary':          [{ key: 'Vary',          value: '*' }], // hint, but not too obvious
            'cache-control': [{ key: 'Cache-Control', value: 'max-age=60' }], // browser-caching timer
            'content-type':  [{ key: 'Content-Type',  value: 'text/plain' }], // can't return binary (yet?)
        },
        body: 'Access Denied\n',
    };

    callback(null, response);
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据引用者限制对AWS S3存储桶的访问 的相关文章

随机推荐

  • SignalR + 通过操作方法将消息发布到集线器

    我正在使用 SignalR 的集线器功能 https github com SignalR SignalR 向所有订阅的客户端发布消息 public class NewsFeedHub Hub public void Send string
  • 从文本中删除锚点

    我需要从某些文本中删除锚标记 但似乎无法使用正则表达式来完成此操作 只是锚标记 而不是其内容 例如 a href http www google com target blank google a 会成为google 确切地说 使用正则表达
  • 如何访问用户控件 WinForm 中托管表单上的控件

    在 Visual Studio 中 如何访问托管用户控件的表单上的控件 例如 当用户控件中的文本框中的文本发生更改时 我希望另一个用户控件中的另一个文本框中的文本也发生更改 这两个用户控件都托管在同一窗体上 提前致谢 如果您需要不同的 UI
  • Pandas 将表写入 MySQL:“无法回滚”

    我需要帮助才能使其正常工作 我有一个pd DataFrame df 我需要将其加载到 MySQL 数据库 我不明白错误消息的含义以及如何修复它 任何帮助将不胜感激 这是我尝试过的 import MySQLdb from pandas io
  • 如何查看 Sybase 中的列元数据?

    我有一个同事给我的列列表 但这些列驻留在数据库中的不同表中 Sybase中有某种工具可以查询列所属的表吗 我已经尝试过谷歌搜索这种工具 但到目前为止还没有成功 syscolumns 保存列元数据 从 syscolumns 中选择 其中 na
  • Jupyter Notebook:在代码块中启用垂直滚动

    如何在 jupyter 笔记本的代码块中启用垂直滚动 我以前不小心做过 但现在无法重现 我发现已设置autoscroll true使用文本编辑器在文件本身中 然而 我这样做了 它已经有一个设置 scrolled true 在笔记本中 它只有
  • 如何在 Sass 中使用 Ruby/Rails 变量?

    有没有办法在 Sass 文件中使用 Ruby 应用程序中的变量 您可以将 erb 扩展名添加到 sass 文件中 然后像在常规 erb 文件中一样添加变量 更多信息 http guides rubyonrails org asset pip
  • 如何更改 .vimrc 在 .vim 中的位置

    如何更改 vim 文件夹和 vimrc 文件的位置 以便可以使用两个 或更多 独立版本的 vim 有没有办法在从源代码编译 vim 时进行配置 也许是 feature h 中的一个条目 我为什么要做这样的事情 我必须处理使用 python2
  • 如何知道 matchTemplate 是否找到对象?

    I used this回答并编写了我自己的程序 但我有一个具体的问题 如果图像中没有物体 matchTemplate不会引发错误 而且我不知道有什么方法可以检查是否matchTemplate无论是否找到该对象 任何人都可以给我建议 或者给我
  • 使用 Axis Client API 时未调用将 HTTP 标头添加到 HTTP 请求的处理程序

    我正在使用 Axis API 访问 Axis HTTP 服务器 API的文档可以找到here 我正在使用以下代码将处理程序添加到服务器 service属于 java xml rpc Service 类型 HandlerRegistry re
  • Android:如何以编程方式访问 AVD 管理器中显示的设备序列号(API 版本 8)

    如何以编程方式访问下图中显示的值 这是硬件序列号 要访问它 安卓Q gt SDK 29 android Manifest permission READ PRIVILEGED PHONE STATE是必须的 只有系统应用程序可以需要此权限
  • 如何在Scala 3中使用akka?

    如何在 Scala 3 中使用 akka 使用 scala 3 时找不到 akka 依赖项 sbt 错误 error not found Users admin ivy2 localcom typesafe akka akka actor
  • 在 html 中以正斜杠开头,表示“href”

    我最近开始学习html 真正让我困惑的一件事是为什么有些链接在路径之前有一个正斜杠 而有些链接没有 ie vs dt a href reset index html Reset CSS a dt 一个是相对路径 一个是绝对路径 href 到
  • 使用 Proguard 删除 Google Play 服务库中未使用的类

    我正在尝试摆脱未使用的类Google Play Services图书馆 我已经创建了带有单个空活动的全新 Android 项目 该项目不使用任何来自Google Play Services图书馆 所以我希望 当我构建版本 包括在我的配置中运
  • 为特定应用打开miui省电模式

    我正在开发 VoIP 呼叫应用程序 并且当省电模式打开时 会错过通过 FCM 发送的呼叫MIUI 这种情况经常发生 我希望用户打开Battery saver activity对于我自己的应用程序 并且在省电模式中对该应用程序没有限制 For
  • 在 Node.js 中读取文件

    我对在 Node js 中读取文件感到非常困惑 fs open start html r function err fileToRead if err fs readFile fileToRead encoding utf 8 functi
  • 如何计算以GPS坐标为中心的地球上的圆上的点?

    在 KML 中画一个圆 如何获取地球上某个点的 GPS 坐标 例如以十进制格式 并生成近似于以该点为中心的圆的多边形的坐标 具有 20 多个数据点的多边形看起来像一个圆形 数据点越多 圆就越好看 我正在编写一个生成 KML 的程序 但不知道
  • 从字节数组创建私钥

    有没有办法从字节数组生成私钥 我使用 getEncoded 方法获取了这个字节数组 但现在我必须将其转换回 PrivateKey 谢谢 武克 我也在寻找这个答案 终于找到了 keyBytes 是最初使用 getEncoded 创建的字节数组
  • 在 Java FX 工作线程中不断更新 UI

    I have Label label在我的 FXML 应用程序中 我希望这个标签每秒改变一次 目前我使用这个 Task task new Task
  • 根据引用者限制对AWS S3存储桶的访问

    我试图限制对 S3 存储桶的访问 并仅允许基于引用来源的列表中的某些域 存储桶策略基本上是 Version 2012 10 17 Id http referer domain lock Statement Sid Allow get req