Python, HTTPS GET with basic authentication

Im trying to do a HTTPS GET with basic authentication using python. Im very new to python and the guides seem to use diffrent librarys to do things. (http.client, httplib and urllib). Can anyone show me how its done? How can you tell the standard library to use?

301520 次浏览

更新: OP 使用 Python3,因此添加一个使用 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

Part of the basic authentication header consists of the username and password encoded as Base64.

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

在 HTTP 头中,您将看到这一行 Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=。编码的字符串根据您的用户名和密码而变化。

现在我们需要一个写入 HTTP 响应的位置和一个 curl 连接句柄。

response = cStringIO.StringIO()
conn = pycurl.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()

In Python 3 the following will work. I am using the lower level http.client from the standard library. Also check out section 2 of Rfc2617 for details of basic authorization. This code won't check the certificate is valid, but will set up a https connection. See the http.client docs on how to do that.

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()

下面是使用证书验证在 Python3urllib.request中执行 基本认证的正确方法。

请注意,certifi不是强制性的。您可以使用您的 OS bundle (可能仅限于 * nix)或自己发布 Mozilla 的 CA Bundle。或者,如果您通信的主机只有几个,那么将您自己的 CA 文件从主机的 CA 连接起来,这可以降低由另一个损坏的 CA 引起的 MitM攻击的风险。

#!/usr/bin/env python3




import urllib.request
import ssl


import certifi




context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(certifi.where())
httpsHandler = urllib.request.HTTPSHandler(context = context)


manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
manager.add_password(None, 'https://domain.com/', 'username', 'password')
authHandler = urllib.request.HTTPBasicAuthHandler(manager)


opener = urllib.request.build_opener(httpsHandler, authHandler)


# Used globally for all urllib.request requests.
# If it doesn't fit your design, use opener directly.
urllib.request.install_opener(opener)


response = urllib.request.urlopen('https://domain.com/some/path')
print(response.read())

Use the power of Python and lean on one of the best libraries around: 请求

import requests


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

变量 r (请求响应)有更多可以使用的参数。最好的办法就是打开交互式解释器,玩玩它,或者阅读 请求文档。

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'})

根据@AndrewCox 的回答,有一些小小的改进:

from http.client import HTTPSConnection
from base64 import b64encode




client = HTTPSConnection("www.google.com")
user = "user_name"
password = "password"
headers = {
"Authorization": "Basic {}".format(
b64encode(bytes(f"{user}:{password}", "utf-8")).decode("ascii")
)
}
client.request('GET', '/', headers=headers)
res = client.getresponse()
data = res.read()

注意,如果使用 bytes函数而不是 b""函数,则应该设置编码。

只使用标准模块,不使用手动头编码

... 这似乎是预期的,最便携的方式

the concept of python urllib is to group the numerous attributes of the request into various managers/directors/contexts... which then process their parts:

import urllib.request, ssl


# to avoid verifying ssl certificates
httpsHa = urllib.request.HTTPSHandler(context= ssl._create_unverified_context())


# setting up realm+urls+user-password auth
# (top_level_url may be sequence, also the complete url, realm None is default)
top_level_url = 'https://ip:port_or_domain'
# of the std managers, this can send user+passwd in one go,
# not after HTTP req->401 sequence
password_mgr = urllib.request.HTTPPasswordMgrWithPriorAuth()
password_mgr.add_password(None, top_level_url, "user", "password", is_authenticated=True)


handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# create OpenerDirector
opener = urllib.request.build_opener(handler, httpsHa)


url = top_level_url + '/some_url?some_query...'
response = opener.open(url)


print(response.read())
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))

如果使用令牌,则密码应为 ''

对我有用。

GET & POST 请求通常用于提交表单

Views.py

def index(request)
col1 = float(request.GET.get('col1'))

Html

<div class="form-group col-md-2">
<label for="Col 1">Price</label>
<input type="number" class="form-control" id="col1" name="col1">
</div>