Python 请求:POST 请求删除 Authorization 标头

use*_*113 11 python http http-headers python-requests authorization-header

我正在尝试使用 Python requests 库发出 API POST 请求。我正在传递一个Authorization标头,但是当我尝试调试时,我可以看到标头正在被删除。我不知道是怎么回事。

这是我的代码:

access_token = get_access_token()
bearer_token = base64.b64encode(bytes("'Bearer {}'".format(access_token)), 'utf-8')
headers = {'Content-Type': 'application/json', 'Authorization': bearer_token}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, data=data)
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,我Authorization在请求参数中手动设置了标头,但它缺少实际请求的标头: {'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.4.3 CPython/2.7.9 Linux/4.1.19-v7+'}

另外一条信息是,如果我将 POST 请求更改为 GET 请求,则Authorization标头会正常通过!

为什么这个库会丢弃 POST 请求的标头,我该如何让它工作?

使用请求库的 v2.4.3 和 Python 2.7.9

kma*_*ork 18

TLDR

您请求的 url 将 POST 请求重定向到不同的主机,因此请求库会删除Authoriztion标头,以免泄露您的凭据。要解决这个问题,您可以覆盖请求Session类中的负责方法。

细节

在请求 2.4.3 中,reqeuests删除Authorization标头的唯一地方是当请求被重定向到不同的主机时。这是相关代码

if 'Authorization' in headers:
    # If we get redirected to a new host, we should strip out any
    # authentication headers.
    original_parsed = urlparse(response.request.url)
    redirect_parsed = urlparse(url)

    if (original_parsed.hostname != redirect_parsed.hostname):
        del headers['Authorization']
Run Code Online (Sandbox Code Playgroud)

在较新版本的 中requestsAuthorization标头将在其他情况下被删除(例如,如果重定向是从安全协议到非安全协议)。

因此,在您的情况下可能发生的情况是您的 POST 请求被重定向到不同的主机。您可以使用请求库为重定向主机提供身份验证的唯一方法是通过.netrc文件。遗憾的是,这只允许您使用 HTTP 基本身份验证,这对您没有多大帮助。在这种情况下,最好的解决方案可能是子类化requests.Session并覆盖此行为,如下所示:

from requests import Session

class NoRebuildAuthSession(Session):
    def rebuild_auth(self, prepared_request, response):
        """
        No code here means requests will always preserve the Authorization
        header when redirected.
        Be careful not to leak your credentials to untrusted hosts!
        """

session = NoRebuildAuthSession()
response = session.post('https://myserver.com/endpoint', headers=headers, data=data)
Run Code Online (Sandbox Code Playgroud)

编辑

我已经向 github 上的请求库打开了一个拉取请求,以在发生这种情况时添加警告。它一直在等待第二次批准合并(已经三个月了)。