【发布时间】:2016-05-07 22:38:23
【问题描述】:
我正在使用Python 3.5.1 和Requests 2.9.1。我的用例如下:在向资源服务器 R 发出请求时,我需要从服务 T 进行身份验证(获取令牌)并将其用作 Authorization 标头的值。令牌在某个时候到期,需要一个新令牌被取走。
我有一个使用requests 的应用程序,它在启动时首先获取一个令牌并记住它 - 设置在用于对 R 的请求的Session 中。从那时起 3 分钟,一切都像一个魅力。 3 分钟后,我收到 unauthorized 响应,因为令牌无效。
我将Session 用于所有请求除了用于身份验证;此调用会更新 Session 上的 Authorization 标头以供其他请求使用。
我创建了代码以在检测到unauthorized 时自动重新验证,使用response 挂钩(仅在Session 上设置),代码如下:
def __hook(self, res, *args, **kwargs):
if res.status_code == requests.codes.unauthorized:
print('Token expired, refreshing')
self.auth() # sets the token on self.__session
req = res.request
print('Resending request', req.method, req.url, req.headers)
req.headers['Authorization'] = self.__session.headers['Authorization'] # why is it needed?
return self.__session.send(res.request)
基本上,它甚至可以工作。不过有几个问题:
为什么即使会话已更新并用于重新发送原始请求,也需要重新设置请求上的
Authorization标头?没有该行,应用程序将继续刷新令牌,因为新令牌从未使用过,这可以在输出中看到,令牌是导致自动刷新的原始令牌。如何使代码更健壮,即防止无限递归(我不确定在现实中是否可能,但在重试请求上设置
Authorization标头的行将继续一个开)?我正在考虑设置一个自定义标头,如果钩子发现失败的请求有它,它就不会重新验证并重新发送。有更好的吗? 编辑: 事实证明,如果配置错误,可能会获得(几乎)无限循环(毕竟它是递归的):令牌被用于一个环境(如 STAGING),但是资源服务器来自另一个 (TEST) -auth请求将成功,但资源服务器的令牌实际上不正确。目前我实现了上面提到的“特殊”标头解决方案。
这是一般的好方法还是有什么更适合requests中的任务?
【问题讨论】:
-
如果不重置授权标头,客户端将没有新令牌,并且没有新令牌,它将无法在接下来的三分钟后发出请求。
-
你提前知道token什么时候到期吗?如果是这样,在令牌过期之前提前刷新令牌会更有效。
-
有点坏死,但我知道为什么需要重置授权标头。这是因为
res.request是一个PreparedRequest,它有一个头文件的副本,这是在PreparedRequest中重新配置头文件的另一种方法:request.prepare_headers(self._session.headers) -
另外,pykube-ng 有一组非常好的示例,说明如何在其源代码中也能做到这一点:codeberg.org/hjacobs/pykube-ng/src/branch/main/pykube/http.py