python - Django 休息框架 : redirect to Amazon S3 fails when using Token Authentication

标签 python django amazon-s3 http-headers django-rest-framework

我在 DRF 中使用 token 身份验证,对于某个 API 调用,我想重定向到 S3(使用像 https://my_bucket.s3.amazonaws.com/my/file/path/my_file 这样的 URL .jpg?Signature=MY_AWS_SIGNATURE&AWSAccessKeyId=MY_AWS_ACCESS_KEY_ID)。但是,我从 AWS 收到以下错误:

<Error>
  <Code>InvalidArgument</Code>
  <Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message>
  <ArgumentName>Authorization</ArgumentName>
  <ArgumentValue>Token a3f61c10592272399099882eb178bd4b755af5bf</ArgumentValue>
  <RequestId>E4038228DD1E6330</RequestId>
  <HostId>9c2xX59cugrR0CHjxQJR8IBE4MXBbNMX+wX2JdPJEuerkAftc32rufotM7COKLIavakByuRUXOo=</HostId>
</Error>

很明显为什么会发生这种情况——带有 DRF token 的 Authorization header 随重定向一起传播,而 S3 不喜欢它。

在研究并尝试了一百万种方法来摆脱该 header 之后,我放弃并决定尝试使用 S3 值覆盖 header :AWS MY_AWS_SIGNATURE:MY_AWS_ACCESS_KEY_ID,之后我得到一个不同的错误:

<Error>
  <Code>InvalidArgument</Code>
  <Message>Unsupported Authorization Type</Message>
  <ArgumentName>Authorization</ArgumentName>
  <ArgumentValue>Token a3f61c10592272399099882eb178bd4b755af5bf</ArgumentValue>
  <RequestId>94D5ADA28C6A5BFB</RequestId>
  <HostId>1YznL6UC3V0+nCvilsriHDAnP2/h3MoDlIJ/L+0V6w7nbHbf2bSxoQflujGmQ5PrUZpNiH7GywI=</HostId>
</Error>

如您所见,最终结果是相同的——即使我在响应中覆盖了 Authorization header ,它仍然保留原始 DRF token 身份验证值。

# relevant portion of my response construction
headers = {'Location': 'https://my_bucket.s3.amazonaws.com/my/file/path/my_file.jpg',
           'Authorization': 'AWS %s:%s' % (params['AWSAccessKeyId'], params['Signature'])}
return Response(status=status.HTTP_302_FOUND, headers=headers)

所以,我的问题是,如何删除或覆盖 DRF 响应中的 Authorization header ?

最佳答案

重定向 Authorization header 是客户端的责任(例如浏览器、cURL、HTTP 库/工具包)。

例如,Paw,我查询 API 的工具包提供了这种配置: Paw app redirect configuration

所以基本上,主流浏览器倾向于重定向 Authorization header ,这会导致 S3 上的冲突。

此外,我怀疑您误解了重定向的执行方式:

  1. 当 DRF 发出重定向时,它会向客户端返回一个 HTTP 301 或 302 响应,其中包含新的 Location header (请求不是直接通过“转发” DRF)
  2. 然后,客户端请求这个新的 URI

最后,当您发出 302 时,您没有覆盖任何 Authorization header ,因为这是对客户端的响应(可以携带Authorization header ,但这没用)。


现在,您有一堆解决方案(因此不是现成的......):

  1. 通过不同的 header 传递您的 token 以避免冲突(例如 X-Token)
  2. 通过 HTTP GET 参数传递您的 token (?token=blah)
  3. 使用您的 DRF View 代理 S3 对象(然后不重定向)

前两个解决方案可能会以某种方式破坏 API 的一致性,但在某些方面是足够公平的。他们需要自定义 TokenAuthenticationget_authorization_header(来自 rest_framework.authorization)。

最后一个是透明的,但可能完全不合适,具体取决于您在 S3 上获取的对象和/或您的托管限制...

这就是我现在能告诉你的全部。如您所知,I've been stuck with the same situation too .如果有人能提出更好的解决方案,我将非常高兴。

关于python - Django 休息框架 : redirect to Amazon S3 fails when using Token Authentication,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33714122/

相关文章:

python - 在 python 的一行中有条件地不产生任何结果

c# - 在我的C#客户端中接收意外的udp数据包

python - 如何避免 django 1.11 和 redis 3.0 上的缓存错误

python - Django url 是如何匹配的?

python - 使用 boto3 从 s3 下载时使用文件名作为文件名

android - 主机名与证书主题不匹配

python - Python中len()和pop()的效率

python - sklearn.linear_model.LogisticRegression 每次都返回不同的系数,尽管设置了 random_state

python - 如何从 Wagtail CMS 中的 streamfield 检索页面内容?

amazon-web-services - 在 AWS 中使用 S3 listObjectVersions 需要什么权限?