/auth
端点最初设置会话Cookie,然后在进一步的请求中用于身份验证。
至于我的问题:由于身份验证基于活动会话,因此一旦连接断开,Cookie就不再有效,因此必须重新启动。据我所知,requests
是基于urllib3
的,它默认情况下使连接保持活动状态。然而,经过几次测试后,我注意到在某些情况下,连接无论如何都会断开。
我使用了requests
模块中的Session
对象,并测试了断开连接所需的时间,如下所示:
from requests import session
import logging
import time import time, sleep
logging.basicConfig(level=logging.DEBUG)
def tt(interval):
credentials = {"username":"user","password":"pass"}
s = Session()
r = s.post("https://<host>:<port>/auth", json=credentials)
ts = time()
while r.status_code is 200:
r = s.get("https://<host>:<port>/some/other/endpoint")
sleep(interval)
return time() - ts # Seconds until connection drop
可能不是解决此问题的最佳方法,但我让该函数运行了两次,一次间隔1秒,另一次间隔1分钟。两者都运行了大约一个小时,直到我不得不手动停止执行。
但是,当我交换while
循环中的两行时,这意味着在最初的POST /auth
请求之后有1分钟的延迟,以下GET
请求失败,并显示401 Unauthorized
,并且预先记录了以下消息:
DEBUG:urllib3.connectionpool:Resetting dropped connection: <host>
由于在我的Prod脚本中,请求的间隔可能从几分钟到几个小时不等,因此我必须事先知道这些会话保持活动的时间以及该规则是否有一些例外(例如,如果在最初的POST /auth
之后一小段时间内没有请求,则断开连接)。
那么,requests
或更确切地说是urllib3
使连接保持活动状态多长时间,是否可以无限期延长该时间?
或者是服务器而不是requests
丢弃了连接?
使用requests.Session
,keep-alive is handled for you automatically。
/auth
调用后不断轮询服务器的循环的第一个版本中,服务器不会因为随后发生的GET
而断开连接。在第二个版本中,休眠间隔可能会超过服务器配置为保持连接打开的时间量。
根据API的服务器配置,响应标头可能包含一个Keep-Alive
标头,其中包含有关连接至少保持打开多长时间的信息。HTTP/1.0
指定此信息包含在Keep-Alive
头的timeout
参数中。您可以使用此信息确定在服务器断开连接之前您有多长时间。
在HTTP/1.1
中,默认情况下使用持久连接,并且不使用Keep-Alive
头,除非服务器显式实现它以实现向后兼容。由于存在这种差异,客户端无法立即确定连接的确切超时时间,因为它可能仅作为服务器端配置存在。
保持连接打开的关键是继续定期轮询。您使用的时间间隔必须小于服务器配置的连接超时。
需要指出的另一件事是,以这种方式人为地无限期延长会话长度会使人更容易受到session fixation attacks的攻击。您可能需要考虑添加偶尔重新建立会话的逻辑,以最大限度地降低发生此类攻击的风险。