Django Rest框架:重定向到Amazon S3时使用令牌身份验证失败 [英] Django Rest Framework: redirect to Amazon S3 fails when using Token Authentication

查看:514
本文介绍了Django Rest框架:重定向到Amazon S3时使用令牌身份验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在DRF和某个API调用中使用令牌身份验证,要重定向到S3(使用像 https://my_bucket.s3.amazonaws.com/my/file/ ?路径/ my_file.jpg签名= MY_AWS_SIGNATURE&安培; AWSAccessKeyId = MY_AWS_ACCESS_KEY_ID )。但是,我从AWS收到以下错误:

 < Error> 
< Code> InvalidArgument< / Code>
< Message>只允许一个身份验证机制;应仅指定X-Amz-Algorithm查询参数,签名查询字符串参数或授权头应为< / Message>
< ArgumentName>授权< / ArgumentName>
< ArgumentValue>令牌a3f61c10592272399099882eb178bd4b755af5bf< / ArgumentValue>
< RequestId> E4038228DD1E6330< / RequestId>
< HostId> 9c2xX59cugrR0CHjxQJR8IBE4MXBbNMX + wX2JdPJEuerkAftc32rufotM7COKLIavakByuRUXOo =< / HostId>
< / Error>

很明显为什么会发生这种情况 - 授权标题与DRF的令牌传播与重定向,S3不喜欢。



在研究和尝试了一百万种方式摆脱那个标题后,我放弃了并决定使用S3值尝试覆盖标题: AWS MY_AWS_SIGNATURE:MY_AWS_ACCESS_KEY_ID ,之后我收到一个不同的错误:

 <错误> 
< Code> InvalidArgument< / Code>
<消息>不支持的授权类型< / Message>
< ArgumentName>授权< / ArgumentName>
< ArgumentValue>令牌a3f61c10592272399099882eb178bd4b755af5bf< / ArgumentValue>
< RequestId> 94D5ADA28C6A5BFB< / RequestId>
< HostId> 1YznL6UC3V0 + nCvilsriHDAnP2 / h3MoDlIJ / L + 0V6w7nbHbf2bSxoQflujGmQ5PrUZpNiH7GywI =< / HostId>
< / Error>

如您所见,最终结果是一样的 - 即使我覆盖授权在我的回复中,它仍然保留原来的DRF令牌认证值。

  #响应结构的相关部分
headers = {'Location':'https://my_bucket.s3.amazonaws.com/my/file/path/my_file.jpg',
'授权': 'AWS%s:%s'%(params ['AWSAccessKeyId'],params ['Signature'])
返回响应(status = status.HTTP_302_FOUND,headers = headers)

所以,我的问题是,DRF响应中的授权头如何被删除或覆盖?

解决方案

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



例如,Paw,我的工具包来查询我的API那种配置:



所以基本上,主要浏览器往往重定向授权



另外我怀疑你误解了重定向的执行方式:


  1. 当DRF发出重定向时,它向客户端返回一个 HTTP 301或302 响应,其中包含新的位置头(请求不是通过DRF直接转发)

  2. 然后,客户端请求这个新的URI

最后,当您发布授权标题> 302 因为这是对客户端的响应(可以携带授权头,但是没用)。






现在,y ou有一堆解决方案(因此不是开箱即用...):


  1. 通过不同的方式传递你的令牌标题以避免冲突(例如,X-Token)

  2. 通过 HTTP GET 参数(?token = blah

  3. 使用您的DRF视图代理S3对象(不重定向)

前两种解决方案可能会以某种方式破坏您的API的一致性,但在某种程度上是公平的。他们需要一个自定义的 TokenAuthentication get_authorization_header (从 rest_framework.authorization )。



最后一个是透明的,但可能完全不适用,具体取决于您在S3和/或主机约束条件下获取的对象...

现在我可以告诉你了。如你所知,我一直困在同样的情况下 。如果有人可以提出一个更好的解决方案,我会很高兴。


I'm using token authentication in DRF and for a certain API call, want to redirect to S3 (using a URL like https://my_bucket.s3.amazonaws.com/my/file/path/my_file.jpg?Signature=MY_AWS_SIGNATURE&AWSAccessKeyId=MY_AWS_ACCESS_KEY_ID). However, I get the following error from 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>

It's clear why this happens--the Authorization header with DRF's token is propagated with the redirect and S3 doesn't like it.

After researching and trying a million ways to get rid of that header, I gave up and decided to try and override the header with an S3 value: AWS MY_AWS_SIGNATURE:MY_AWS_ACCESS_KEY_ID, after which I get a different error:

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

As you can see, the end result is the same--even if I override the Authorization header in my response, it still keeps the original DRF token authentication value.

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

So, my question is, how can the Authorization header in a DRF response be either removed or overridden?

解决方案

Redirecting the Authorization header is the responsibility of the client (eg. browsers, cURL, HTTP libraries/toolkits).

For example, Paw, my toolkit to query my APIs offers that kind of configuration:

So basically, major browsers are tend to redirect the Authorization header which cause the conflict on S3.

Also I suspect you misunderstood how redirects are performed:

  1. When DRF issues a redirect, it returns an HTTP 301 or 302 response to the client, containing the new Location header (the request is not "forwarded" directly via DRF)
  2. Then, the client requests this new URI

And finally, you're not overriding any Authorization header when you're emitting your 302 since this is the response... to the client (which can carry an Authorization header but that's useless).


Right now, you have a bunch of solutions (thus not out of the box...):

  1. Passing your token through a different header to avoid the conflict (X-Token for example)
  2. Passing your token through a HTTP GET parameter (?token=blah)
  3. Using your DRF view to proxy the S3 object (no redirect then)

The first two solutions may break in some way the consistency of your API but in some way are fair enough. They would require a custom TokenAuthentication or get_authorization_header (from rest_framework.authorization).

The last one is transparent but may be totally unsuitable depending on the object your're fetching on S3 and/or your hosting constraints...

That's all I can tell you for now. As you know, I've been stuck with the same situation too. I would be so pleased if anyone could suggest a better solution.

这篇关于Django Rest框架:重定向到Amazon S3时使用令牌身份验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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