Python,使用基本认证的HTTPS GET

132 投票
8 回答
362225 浏览
提问于 2025-04-16 23:13

我想用Python做一个带基本认证的HTTPS GET请求。对Python我还很陌生,网上的教程好像用的库都不一样(比如http.client、httplib和urllib)。有没有人能教我怎么做?我该怎么知道用哪个标准库呢?

8 个回答

23

更新:楼主使用的是Python 3。所以这里加一个使用 httplib2 的例子。

import httplib2

h = httplib2.Http(".cache")

h.add_credentials('name', 'password') # Basic authentication

resp, content = h.request("https://host/path/to/resource", "POST", body="foobar")

下面的内容适用于Python 2.6:

我在生产环境中经常使用 pycurl,因为我每天要处理超过1000万次请求。

首先,你需要导入以下内容。

import pycurl
import cStringIO
import base64

基本的身份验证头部包含用户名和密码,这些信息会被编码成Base64格式。

headers = { 'Authorization' : 'Basic %s' % base64.b64encode("username:password") }

在HTTP头部,你会看到这一行 Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=。这个编码后的字符串会根据你的用户名和密码而变化。

现在我们需要一个地方来写入HTTP响应,以及一个curl连接句柄。

response = cStringIO.StringIO()
conn = pycurl.Curl()

我们可以设置各种curl选项。想要查看完整的选项列表,可以 查看这里。链接中的文档是针对libcurl API的,但其他语言的绑定选项是一样的。

conn.setopt(pycurl.VERBOSE, 1)
conn.setopt(pycurlHTTPHEADER, ["%s: %s" % t for t in headers.items()])

conn.setopt(pycurl.URL, "https://host/path/to/resource")
conn.setopt(pycurl.POST, 1)

如果你不需要验证证书。 警告:这很不安全。类似于运行 curl -kcurl --insecure

conn.setopt(pycurl.SSL_VERIFYPEER, False)
conn.setopt(pycurl.SSL_VERIFYHOST, False)

调用 cStringIO.write 来存储HTTP响应。

conn.setopt(pycurl.WRITEFUNCTION, response.write)

当你发起一个POST请求时。

post_body = "foobar"
conn.setopt(pycurl.POSTFIELDS, post_body)

现在进行实际的请求。

conn.perform()

根据HTTP响应代码做一些处理。

http_code = conn.getinfo(pycurl.HTTP_CODE)
if http_code is 200:
   print response.getvalue()
142

利用Python的强大功能,使用其中一个最好的库:requests

import requests

r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass'))
print(r.text)

变量r(请求的响应)有很多其他参数可以使用。最好的办法是打开交互式解释器,自己动手试试,或者阅读requests的文档。

ubuntu@hostname:/home/ubuntu$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass'))
>>> dir(r)
['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'iter_content', 'iter_lines', 'json', 'links', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
>>> r.content
b'{"battery_status":0,"margin_status":0,"timestamp_status":null,"req_status":0}'
>>> r.text
'{"battery_status":0,"margin_status":0,"timestamp_status":null,"req_status":0}'
>>> r.status_code
200
>>> r.headers
CaseInsensitiveDict({'x-powered-by': 'Express', 'content-length': '77', 'date': 'Fri, 20 May 2016 02:06:18 GMT', 'server': 'nginx/1.6.3', 'connection': 'keep-alive', 'content-type': 'application/json; charset=utf-8'})
187

在Python 3中,下面的代码可以正常工作。我使用的是标准库中的较低级别的 http.client。另外,可以查看 rfc2617 的第二部分,了解基本授权的详细信息。这段代码不会检查证书是否有效,但会建立一个https连接。有关如何做到这一点,请查看 http.client 的文档。

from http.client import HTTPSConnection
from base64 import b64encode


# Authorization token: we need to base 64 encode it 
# and then decode it to acsii as python 3 stores it as a byte string
def basic_auth(username, password):
    token = b64encode(f"{username}:{password}".encode('utf-8')).decode("ascii")
    return f'Basic {token}'

username = "user_name"
password = "password"

#This sets up the https connection
c = HTTPSConnection("www.google.com")
#then connect
headers = { 'Authorization' : basic_auth(username, password) }
c.request('GET', '/', headers=headers)
#get the response back
res = c.getresponse()
# at this point you could check the status etc
# this gets the page text
data = res.read()  

撰写回答