URL中的用户名带反斜杠的HTTP身份验证
我需要在进行REST调用时使用HTTP基本认证。在用户名中,我需要提供一个带有连字符的域名,然后用反斜杠来分隔用户名,格式是:DOM-AIN\user_name。密码就比较简单了。
用curl命令可以正常工作:
curl 'https://DOM-AIN\user_name:password@myurl.com'
现在我想把这个放到Python里,但我尝试了requests和urllib/2/3...它们对\、:和@都不太友好。即使我把它们编码成%40等,仍然被当成实际的:,而urllib则认为我在定义一个端口,结果出现了错误:无效的套接字,我记不清了。
所以我尝试用urllib3在头部传递用户名和密码,但我收到了未授权访问的错误,我怀疑是因为我需要以某种方式对用户名进行编码,以处理反斜杠(%5C),但这似乎也不管用。
这是一些不工作的代码:
# Attempt 1
http = urllib3.PoolManager()
url1 = https://ws.....
headers = urllib3.util.make_headers(basic_auth='DOM-AIN\user_name:password')
r1 = http.request('GET', url1, headers=headers)
response = r1.data
# Attempt 2
passwordManager = urllib2.HTTPPasswordMgrWithDefaultRealm()
passwordManager.add_password(None, url, 'DOM-AIN\user_name, password)
authenticationHandler = urllib2.HTTPBasicAuthHandler(passwordManager)
opener = urllib2.build_opener(authenticationHandler)
data = opener.open(url1)
我还有其他尝试用requests的代码,但我现在没有了。如果需要的话,我可以提供这些错误信息,但如果已经知道我哪里做错了,那就太好了...
3 个回答
首先,把你的 DOM-AIN\user_name
转换成 base64
字符串。假设转换后的结果是 XXXXYYYYYYY
。接下来,把这个 base64
字符串放到 HTTP 头部,就像下面的代码所示,使用 urllib2
。
headers = { 'Authorization:' : 'Basic XXXXYYYYYYY' }
req = urllib2.Request(url, data, headers)
我找到了一种使用urllib的方法,灵感来自于这篇帖子提到的FancyURLopener,这让我走上了正确的道路。虽然我尽量让它的工作方式接近curl,但看了Sabuj的回答后,似乎还有其他方法可以正确使用请求头,不过我还没有尝试他的办法。
import urllib
opener = urllib.FancyURLopener()
data = opener.open('https://DOM-AIN**%5C%user_name:password@url.com?whatever_parameters')
response = data.read()
当我只对反斜杠进行了URL编码时,它可以正常工作。但当我对其他字符,比如:和@进行编码时,就不行了。
在Python的字符串中,反斜杠需要进行转义:
username = 'DOM-AIN\\user_name' # OR
username = r'DOM-AIN\user_name' # raw-string literal
举个例子:
import urllib2, base64
request = urllib2.Request('https://example.com')
credentials = base64.b64encode(username + b':' + password)
request.add_header('Authorization', b'Basic ' + credentials)
response = urllib2.urlopen(request)
注意:和HTTPBasicAuthHandler
的代码不同,它总是会发送凭证,而不需要等到收到401
响应和WWW-Authenticate
头。