在 getSignedUrl 过期后,AWS S3 优雅地处理 403 [英] AWS S3 gracefully handle 403 after getSignedUrl expired

查看:45
本文介绍了在 getSignedUrl 过期后,AWS S3 优雅地处理 403的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过过期的 URL 访问 S3 资源时,我试图优雅地处理 403.目前它返回一个 amz xml 错误页面.我上传了一个 403.html 资源,并认为我可以重定向到那个.

I'm trying to gracefully handle the 403 when visiting an S3 resource via an expired URL. Currently it returns an amz xml error page. I have uploaded a 403.html resource and thought I could redirect to that.

存储桶资源是我的应用程序保存/获取的资产.尽管如此,阅读文档我设置存储桶属性以将存储桶作为静态网页页面处理并将 403.html 上传到存储桶根目录.所有公共权限都被阻止,除了对资源 403.html 的公共 GET 访问.在存储桶属性、网站设置中,我将 403.html 指示为错误页面.访问 http://.s3-website-us-east-1.amazonaws.com/some-asset.html 正确重定向到 http://;.s3-website-us-east-1.amazonaws.com/403.html

The bucket resources are assets saved/fetched by my app. Still, reading the docs I set bucket properties to handle the bucket as a static webpage page and uploaded a 403.html to bucket root. All public permissions are blocked, except public GET access to the resource 403.html. In bucket properties, website settings I indicated the 403.html as error page. Visiting http://<bucket>.s3-website-us-east-1.amazonaws.com/some-asset.html redirects correctly to http://<bucket>.s3-website-us-east-1.amazonaws.com/403.html

但是,当我使用 aws-sdk js/node 并调用方法 getSignedUrl('getObject', params) 生成签名 url 时,它返回一个不同的主机 url:https://<bucket>.s3.amazonaws.com/ 从此方法访问过期资源不会被重定向到 403.html.我猜是因为主机地址不同,这就是它不会自动重定向的原因.

However, when I use aws-sdk js/node and call method getSignedUrl('getObject', params) to generate the signed url, it returns a different host url: https://<bucket>.s3.amazonaws.com/ Visiting expired resources from this method do not get redirected to 403.html. I'm guessing that since the host address is different this is the reason it is not automatically redirecting.

我还为条件设置了静态网站路由规则

I have also set up static website routing rules for condition

<Condition>
  <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
  <ReplaceKeyWith>403.html</ReplaceKeyWith>
</Redirect>

仍然没有重定向签名的网址.所以我不知道如何优雅地处理这些过期的 url.任何帮助将不胜感激.

Still that's not redirecting the signed urls. So I'm at a loss of how to gracefully handle these expired urls. Any help would be greatly appreciated.

推荐答案

S3 存储桶有 2 个面向公众的接口,REST 和网站.这就是两个主机名之间的差异,以及您所看到的行为差异.

S3 buckets have 2 public-facing interfaces, REST and website. That is the difference between the two hostnames, and the difference in behavior you are seeing.

它们有两个不同的功能集.

They have two different feature sets.

feature          REST Endpoint       Website Endpoint
---------------- ------------------- -------------------
Access control   yes                 no, public content only
Error messages   XML                 HTML
Redirection      no                  yes, bucket, rule, and object-level
Request types    all supported       GET and HEAD only
Root of bucket   lists keys          returns index document
SSL              yes                 no

来源:http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html

因此,从表中可以看出,REST 端点支持签名 URL,但不支持友好错误,而网站端点支持友好错误,但不支持签名 URL.两者不能混合搭配,因此 S3 本身不支持您尝试执行的操作.

So, as you can see from the table, the REST endpoint supports signed URLs, but not friendly errors, while the website endpoint supports friendly errors, but not signed URLs. The two can't be mixed and matched, so what you're trying to do isn't natively supported by S3.

我通过将存储桶的所有请求通过 EC2 实例上的 HAProxy 传递到存储桶的 REST 端点来解决此限制.

I have worked around this limitation by passing all requests for the bucket through HAProxy on an EC2 instance and on to the REST endpoint for the bucket.

当返回 403 错误消息时,代理使用新的 嵌入式修改响应正文 XMLLua 解释器,在 标签之前添加这个.

When a 403 error message is returned, the proxy modifies the response body XML using the new embedded Lua interpreter, adding this before the <Error> tag.

<?xml-stylesheet type="text/xsl" href="/error.xsl"?>

文件 /error.xsl 是公开可读的,并且使用浏览器端 XSLT 来呈现一个漂亮的错误响应.

The file /error.xsl is publicly readable, and uses browser-side XSLT to render a pretty error response.

代理还在 xml 中注入了几个额外的标签, 以用于输出.生成的 XML 如下所示:

The proxy also injects a couple of additional tags into the xml, <ProxyTime> and <ProxyHTTPCode> for use in the output. The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/error.xsl"?>
<Error><ProxyTime>2015-10-13T17:36:01Z</ProxyTime><ProxyHTTPCode>403</ProxyHTTPCode><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>9D3E05D20C1BD6AC</RequestId><HostId>WvdkvIRIDMjfa/1Oi3DGVOTR0hABCDEFGHIJKLMNOPQRSTUVWXYZ+B8thZahg7W/I/ExAmPlEAQ=</HostId></Error>

然后我通过 XSL 测试改变向用户显示的输出,以确定 S3 抛出的错误条件:

Then I vary the output shown to the user with XSL tests to determine what error condition S3 has thrown:

<xsl:if test="//Code = 'AccessDenied'">
  <p>It seems we may have provided you with a link to a resource to which you do not have access, or a resource which does not exist, or that our internal security mechanisms were unable to reach consensus on your authorization to view it.</p>
</xsl:if>

最后的结果是这样的:

以上是一般的拒绝访问",因为没有提供凭据.这是过期签名的示例.

The above is a general "Access Denied" because no credentials were supplied. Here's an example of an expired signature.

我没有在输出中包含 HostId,因为它既丑陋又嘈杂,而且,如果我需要它,代理会为我捕获并记录它,我可以交叉引用到请求 ID.

I don't include the HostId in the output, since it's ugly and noisy, and, if I ever need it, the proxy captured and logged it for me, and I can cross-reference to the request-id.

当然,作为奖励,通过我的代理运行请求意味着我可以在提供存储桶内容时使用我自己的域名我自己的 SSL 证书,并且我有实时访问日志没有延迟.当proxy和bucket在同一个区域时,额外的数据传输步骤不收取额外费用,我对这个设置很满意.

As a bonus, of course, running the requests through my proxy means I can use my own domain name and my own SSL certificate when serving up bucket content, and I have real-time access logs with no delay. When the proxy is in the same region as the bucket, there is no additional charge for the extra step of data transfer, and I've been very happy with this setup.

这篇关于在 getSignedUrl 过期后,AWS S3 优雅地处理 403的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆