Próbuję wykonać HTTPS GET z podstawowym uwierzytelnianiem przy użyciu Pythona. Jestem bardzo nowy w Pythonie, a przewodniki wydają się używać różnych bibliotek do robienia różnych rzeczy. (http.client, httplib i urllib). Czy ktoś może mi pokazać, jak to się robi? Jak możesz powiedzieć bibliotece standardowej, aby używała?
python
python-3.x
Tom Squires
źródło
źródło
Odpowiedzi:
W Pythonie 3 będą działać następujące rzeczy. Używam http.client niższego poziomu z biblioteki standardowej. Sprawdź również sekcję 2 rfc2617, aby uzyskać szczegółowe informacje na temat podstawowej autoryzacji. Ten kod nie sprawdzi, czy certyfikat jest ważny, ale ustanowi połączenie https. Zobacz dokumentację http.client, aby dowiedzieć się, jak to zrobić.
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()
źródło
request
metody [1] wspomina, że „Ciągi znaków są kodowane jako„ ISO-8859-1 ”, domyślny zestaw znaków HTTP”. Dlatego sugeruję dekodowanie za pomocą „ISO-8859-1” zamiast „ASCII”. [1] docs.python.org/3/library/ ...b"username:password"
używać:bytes(username + ':' + password, "utf-8")
..decode("ascii")
dotyczy tylko konwersjibytes
->str
. Wynik i takb64encode
jest tylko ASCII.Skorzystaj z możliwości Pythona i oprzyj się na jednej z najlepszych bibliotek w zakresie: request
import requests r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass')) print(r.text)
Zmienna r (żąda odpowiedzi) ma dużo więcej parametrów, których możesz użyć. Najlepiej jest wejść do interaktywnego interpretera i pobawić się nim i / lub przeczytać dokumenty z żądaniami .
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'})
źródło
Aktualizacja: OP używa Pythona 3. Dodam więc przykład używając 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")
Poniższe działa dla Pythona 2.6:
Używam
pycurl
dużo w produkcji w procesie, który wykonuje ponad 10 milionów żądań dziennie.Najpierw musisz zaimportować następujące elementy.
import pycurl import cStringIO import base64
Część podstawowego nagłówka uwierzytelniania składa się z nazwy użytkownika i hasła zakodowanych jako Base64.
headers = { 'Authorization' : 'Basic %s' % base64.b64encode("username:password") }
W nagłówku HTTP zobaczysz tę linię
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
. Zakodowany ciąg zmienia się w zależności od nazwy użytkownika i hasła.Potrzebujemy teraz miejsca do zapisania naszej odpowiedzi HTTP i uchwytu połączenia curl.
Możemy ustawić różne opcje podkręcania. Aby uzyskać pełną listę opcji, zobacz to . Połączona dokumentacja dotyczy interfejsu API libcurl, ale opcje nie zmieniają się w przypadku innych powiązań językowych.
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)
Jeśli nie musisz weryfikować certyfikatu. Ostrzeżenie: to jest niebezpieczne. Podobny do biegania
curl -k
lubcurl --insecure
.conn.setopt(pycurl.SSL_VERIFYPEER, False) conn.setopt(pycurl.SSL_VERIFYHOST, False)
Wezwij
cStringIO.write
do przechowywania odpowiedzi HTTP.Kiedy wysyłasz żądanie POST.
post_body = "foobar" conn.setopt(pycurl.POSTFIELDS, post_body)
Złóż rzeczywistą prośbę teraz.
Zrób coś na podstawie kodu odpowiedzi HTTP.
http_code = conn.getinfo(pycurl.HTTP_CODE) if http_code is 200: print response.getvalue()
źródło
Poniżej przedstawiono prawidłowy sposób wykonywania podstawowego uwierzytelniania w Python3
urllib.request
z weryfikacją certyfikatu.Pamiętaj, że
certifi
nie jest to obowiązkowe. Możesz użyć pakietu systemu operacyjnego (prawdopodobnie tylko * nix) lub samodzielnie dystrybuować pakiet CA Mozilli . Jeśli hostów, z którymi się komunikujesz, jest tylko kilka, sam połącz plik CA z urzędów certyfikacji hosta, co może zmniejszyć ryzyko ataku MitM spowodowanego przez inny uszkodzony urząd certyfikacji.#!/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())
źródło
używając tylko standardowych modułów i bez ręcznego kodowania nagłówka
... co wydaje się być zamierzonym i najbardziej przenośnym sposobem
koncepcja python urllib polega na grupowaniu licznych atrybutów żądania w różnych menedżerach / dyrektorach / kontekstach ... które następnie przetwarzają ich części:
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())
źródło
Na podstawie odpowiedzi @AndrewCox z kilkoma drobnymi ulepszeniami:
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()
Uwaga, powinieneś ustawić kodowanie, jeśli używasz
bytes
function zamiastb""
.źródło
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))
Jeśli z tokenem, hasło powinno być
''
.Mi to pasuje.
źródło