Python 请求:POST 请求删除授权 header
Python requests: POST request dropping Authorization header
我正在尝试使用 Python 请求库发出 API POST 请求。我正在通过一个 Authorization
header 但是当我尝试调试时,我可以看到 header 被删除了。我不知道发生了什么。
这是我的代码:
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)
正如您在上面看到的,我在请求参数中手动设置了 Authorization
header,但缺少实际请求的 header:
{'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
header正常通过!
为什么这个库会为 POST 请求删除 header,我该如何让它工作?
使用请求库的 v2.4.3 和 Python 2.7.9
请求文档是这样写的:
Authorization headers set with headers= will be overridden if credentials are specified in .netrc, which in turn will be overridden by the auth= parameter.
Authorization headers will be removed if you get redirected off-host.
您的请求是否被重定向?
如果是这种情况,请尝试在 post 请求中使用此选项禁用重定向:
allow_redirects=False
您可以尝试在headers中使用自定义授权。
定义自定义身份验证class:
class MyAuth(requests.auth.AuthBase):
def __init__(self, bearer_token):
self.username = None
self.bearer_token = bearer_token
def __call__(self, r):
r.headers['Authorization'] = self.bearer_token
return r
然后用这个发送请求:
headers = {'Content-Type': 'application/json'}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, auth=MyAuth(bearer_token), data=data)
如果可行,请接受答案。或者,如果您仍有问题,请告诉我们。
希望这有帮助。
TLDR
您请求的 url 将 POST 请求重定向到不同的主机,因此请求库会删除 Authoriztion
header 以免泄露您的凭据。要解决此问题,您可以覆盖请求 Session
class.
中的负责方法
详情
在请求 2.4.3 中,reqeuests
删除 Authorization
header 的唯一地方是当请求被重定向到不同的主机时。 This is the relevant code:
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']
在 requests
的较新版本中,Authorization
header 将在其他情况下被删除(例如,如果重定向是从安全协议到 non-secure 协议).
那么在您的情况下可能发生的情况是,您的 POST 请求被重定向到不同的主机。您可以使用请求库为重定向主机提供身份验证的唯一方法是通过 .netrc
文件。遗憾的是,这将只允许您使用 HTTP Basic Auth,这对您没有多大帮助。在那种情况下,最好的解决方案可能是 subclass 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)
编辑
我已经在 github 上向请求库打开了一个 pull-request,以便在发生这种情况时添加警告。一直在等待二次审批合并(已经三个月了)
我看到的第一个(也许是实际的)问题是你如何创建 bearer_token
因为你不仅编码你的令牌而且还编码身份验证类型 'Bearer'
据我所知,您只需要对令牌进行编码,并且必须在您的请求中提供空白身份验证类型 + 编码令牌 header:
bearer_token = str(base64.b64encode(access_token.encode()), "utf8")
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(bearer_token)}
如果它(也是)重定向问题,您可以简单地找到正确的位置并向此 url 发出请求,或者您可能会考虑在 body 内发送访问令牌你的 POST
如果服务器接受这个。
来自文档:Requests will attempt to get the authentication credentials for the URL’s hostname from the user’s netrc file. The netrc file overrides raw HTTP authentication headers set with headers=.
If credentials for the hostname are found, the request is sent with HTTP Basic Auth.
如果您被重定向,您可以尝试使用 allow_redirects=false
使用 'request' 库在 POST 请求中发送授权 header。在 Python
只需使用这个:
requests.post('https://api.github.com/user', auth=('user', 'pass'))
这是一个基本的授权。
我正在尝试使用 Python 请求库发出 API POST 请求。我正在通过一个 Authorization
header 但是当我尝试调试时,我可以看到 header 被删除了。我不知道发生了什么。
这是我的代码:
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)
正如您在上面看到的,我在请求参数中手动设置了 Authorization
header,但缺少实际请求的 header:
{'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
header正常通过!
为什么这个库会为 POST 请求删除 header,我该如何让它工作?
使用请求库的 v2.4.3 和 Python 2.7.9
请求文档是这样写的:
Authorization headers set with headers= will be overridden if credentials are specified in .netrc, which in turn will be overridden by the auth= parameter.
Authorization headers will be removed if you get redirected off-host.
您的请求是否被重定向?
如果是这种情况,请尝试在 post 请求中使用此选项禁用重定向:
allow_redirects=False
您可以尝试在headers中使用自定义授权。
定义自定义身份验证class:
class MyAuth(requests.auth.AuthBase):
def __init__(self, bearer_token):
self.username = None
self.bearer_token = bearer_token
def __call__(self, r):
r.headers['Authorization'] = self.bearer_token
return r
然后用这个发送请求:
headers = {'Content-Type': 'application/json'}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, auth=MyAuth(bearer_token), data=data)
如果可行,请接受答案。或者,如果您仍有问题,请告诉我们。 希望这有帮助。
TLDR
您请求的 url 将 POST 请求重定向到不同的主机,因此请求库会删除 Authoriztion
header 以免泄露您的凭据。要解决此问题,您可以覆盖请求 Session
class.
详情
在请求 2.4.3 中,reqeuests
删除 Authorization
header 的唯一地方是当请求被重定向到不同的主机时。 This is the relevant code:
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']
在 requests
的较新版本中,Authorization
header 将在其他情况下被删除(例如,如果重定向是从安全协议到 non-secure 协议).
那么在您的情况下可能发生的情况是,您的 POST 请求被重定向到不同的主机。您可以使用请求库为重定向主机提供身份验证的唯一方法是通过 .netrc
文件。遗憾的是,这将只允许您使用 HTTP Basic Auth,这对您没有多大帮助。在那种情况下,最好的解决方案可能是 subclass 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)
编辑
我已经在 github 上向请求库打开了一个 pull-request,以便在发生这种情况时添加警告。一直在等待二次审批合并(已经三个月了)
我看到的第一个(也许是实际的)问题是你如何创建 bearer_token
因为你不仅编码你的令牌而且还编码身份验证类型 'Bearer'
据我所知,您只需要对令牌进行编码,并且必须在您的请求中提供空白身份验证类型 + 编码令牌 header:
bearer_token = str(base64.b64encode(access_token.encode()), "utf8")
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(bearer_token)}
如果它(也是)重定向问题,您可以简单地找到正确的位置并向此 url 发出请求,或者您可能会考虑在 body 内发送访问令牌你的 POST
如果服务器接受这个。
来自文档:Requests will attempt to get the authentication credentials for the URL’s hostname from the user’s netrc file. The netrc file overrides raw HTTP authentication headers set with headers=.
If credentials for the hostname are found, the request is sent with HTTP Basic Auth.
如果您被重定向,您可以尝试使用 allow_redirects=false
使用 'request' 库在 POST 请求中发送授权 header。在 Python 只需使用这个:
requests.post('https://api.github.com/user', auth=('user', 'pass'))
这是一个基本的授权。