我尝试使用python进行基本身份验证的HTTPS GET。我是python的新手,导游似乎使用不同的图书馆来做事。 (http.client,httplib和urllib)。谁能告诉我它是如何完成的?你怎么能告诉标准库使用?
答案 0 :(得分:73)
在Python 3中,以下内容可行。我正在使用标准库中的较低级别http.client。有关基本授权的详细信息,请查看rfc2617的第2部分。此代码不会检查证书是否有效,但会设置https连接。请参阅http.client文档,了解如何执行此操作。
from http.client import HTTPSConnection
from base64 import b64encode
#This sets up the https connection
c = HTTPSConnection("www.google.com")
#we need to base 64 encode it
#and then decode it to acsii as python 3 stores it as a byte string
userAndPass = b64encode(b"username:password").decode("ascii")
headers = { 'Authorization' : 'Basic %s' % userAndPass }
#then connect
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()
答案 1 :(得分:35)
利用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'})
答案 2 :(得分:19)
更新:OP使用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()
我们可以设置各种卷曲选项。有关选项的完整列表,see this。链接文档适用于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 -k
或curl --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()
答案 3 :(得分:14)
在Python3 basic auth中使用证书验证执行urllib.request
的正确方法如下。
请注意,certifi
不是强制性的。您可以使用自己的操作系统捆绑包(可能仅限* nix)或自行分发Mozilla's 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())
答案 4 :(得分:1)
...这似乎是预期的且最可移植的方式
python urllib的概念是将请求的众多属性分组为各种管理器/导演/上下文...,然后处理它们的各个部分:
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())
答案 5 :(得分:0)
基于@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""
,则应该设置编码。
答案 6 :(得分:0)
GET & POST 请求通常用于提交表单。这是它的用法的一个简单例子
视图.py
def index(request)
col1 = float(request.GET.get('col1'))
index.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>
答案 7 :(得分:-1)
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))
如果使用令牌,则密码应为''
。
对我有用。