在getSignedUrl过期后,AWS S3优雅地处理403

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

存储桶资源是由我的应用程序保存/获取的资产。 尽管如此,阅读文档我设置桶属性来处理桶作为一个静态网页页面,并上传403.html到桶根。 除了公共GET访问资源403.html外,所有公共权限都被阻止。 在存储区属性中,我将网址设置为403.html作为错误页面。 访问http://<bucket>.s3-website-us-east-1.amazonaws.com/some-asset.html正确重定向到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/ Visiting来自此方法的过期资源不会重定向到403.html。 我猜测,由于主机地址不同,这是它不会自动重定向的原因。

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

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

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


S3存储桶有2个面向公众的界面,REST和网站。 这是两个主机名称之间的区别,以及您所看到的行为差异。

他们有两个不同的功能集。

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本地支持。


我已经通过在EC2实例上通过HAProxy的所有请求传递给存储桶的REST端点,从而解决了此限制。

当返回403错误消息时,代理使用新的嵌入式Lua解释器修改响应正文XML,并在<Error>标签前添加。

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

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

该代理还向xml中输入了一些附加标签, <ProxyTime><ProxyHTTPCode>用于输出中。 生成的XML如下所示:

<?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引发了什么错误条件:

<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>

最终结果如下所示:

浏览器这个行为的截图示例

以上是一般性的“访问被拒绝”,因为没有提供凭据。 以下是过期签名的示例。

过期签名的截图

我不在输出中包含HostId ,因为它非常丑陋,而且如果我需要它,代理会为我捕获并记录它,并且可以交叉引用请求标识。

当然,作为奖励,通过我的代理运行请求意味着我可以在提供存储桶内容时使用自己的域名和我自己的SSL证书,并且可以毫不拖延地实时访问日志。 当代理服务器与存储区位于同一区域时,额外的数据传输步骤不需要额外的费用,并且我对此设置非常满意。

链接地址: http://www.djcxy.com/p/93539.html

上一篇: AWS S3 gracefully handle 403 after getSignedUrl expired

下一篇: AmazonS3FullAccess managed policy on a group doesn't give S3 permission?