Python, HTTPS GET с базовой аутентификацией
Я пытаюсь сделать HTTPS GET с базовой аутентификацией с использованием Python. Я очень новичок в python, и в руководствах, похоже, используются разные библиотеки. (http.client, httplib и urllib). Может кто-нибудь показать мне, как это сделано? Как вы можете указать стандартную библиотеку для использования?
8 ответов
В Python 3 будет работать следующее. Я использую http.client более низкого уровня из стандартной библиотеки. Также проверьте секцию 2 rfc2617 для деталей базовой авторизации. Этот код не проверяет действительность сертификата, но устанавливает соединение 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()
Используйте возможности Python и опирайтесь на одну из лучших библиотек: запросы
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'})
Обновление: 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
много в производстве для процесса, который выполняет более 10 миллионов запросов в день.
Сначала вам нужно будет импортировать следующее.
import pycurl
import cStringIO
import base64
Часть основного заголовка аутентификации состоит из имени пользователя и пароля, закодированных как Base64.
headers = { 'Authorization' : 'Basic %s' % base64.b64encode("username:password") }
В заголовке HTTP вы увидите эту строку Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
, Закодированная строка изменяется в зависимости от вашего имени пользователя и пароля.
Теперь нам нужно место для записи нашего HTTP-ответа и дескриптор скручиваемого соединения.
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 -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()
Правильный способ сделать базовую аутентификацию в Python3 urllib.request
с подтверждением сертификата следует.
Обратите внимание, что certifi
не является обязательным Вы можете использовать свой пакет ОС (вероятно, только * nix) или распространять CA Bundle от Mozilla самостоятельно. Или, если хостов, с которыми вы общаетесь, всего лишь несколько, объедините файл CA самостоятельно из CA хостов, что может снизить риск атаки MitM, вызванной другим поврежденным CA.
#!/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())
На основе ответа @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""
.
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))
Если с токеном, пароль должен быть
''
.
Меня устраивает.
с использованием только стандартных модулей и без ручного кодирования заголовков
... что кажется предполагаемым и наиболее переносимым способом
концепция 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())
Запрос GET & POST обычно используется для отправки форм. Вот краткий пример его использования
Views.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>