Estoy tratando de hacer un HTTPS GET con autenticación básica usando python. Soy muy nuevo en Python y las guías parecen usar diferentes bibliotecas para hacer cosas. (http.client, httplib y urllib). ¿Alguien puede mostrarme cómo se hace? ¿Cómo puede indicarle a la biblioteca estándar que se utilice?
python
python-3.x
Tom Squires
fuente
fuente
Respuestas:
En Python 3 funcionará lo siguiente. Estoy usando el http.client de nivel inferior de la biblioteca estándar. Consulte también la sección 2 de rfc2617 para obtener detalles sobre la autorización básica. Este código no verificará que el certificado sea válido, pero establecerá una conexión https. Consulte los documentos http.client sobre cómo hacerlo.
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()
fuente
request
documentación del método [1] menciona que "Las cadenas están codificadas como" ISO-8859-1 ", el juego de caracteres predeterminado para HTTP". Así que sugiero decodificar con "ISO-8859-1" en lugar de "ASCII". [1] docs.python.org/3/library/…b"username:password"
, usar:bytes(username + ':' + password, "utf-8")
..decode("ascii")
es solo para labytes
->str
conversión. Deb64encode
todos modos, el resultado de es solo ASCII.Utilice el poder de Python y apóyese en una de las mejores bibliotecas: solicitudes
import requests r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass')) print(r.text)
La variable r (solicita respuesta) tiene muchos más parámetros que puede usar. Lo mejor es entrar en el intérprete interactivo y jugar con él, y / o leer documentos de solicitudes .
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'})
fuente
Actualización: OP usa Python 3. Así que agregue un ejemplo usando http
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")
Lo siguiente funciona para Python 2.6:
yo suelo
pycurl
mucho en producción para un proceso que hace más de 10 millones de solicitudes por día.Primero deberá importar lo siguiente.
import pycurl import cStringIO import base64
Parte del encabezado de autenticación básica consta del nombre de usuario y la contraseña codificados como Base64.
headers = { 'Authorization' : 'Basic %s' % base64.b64encode("username:password") }
En el encabezado HTTP verá esta línea
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
. La cadena codificada cambia según su nombre de usuario y contraseña.Ahora necesitamos un lugar para escribir nuestra respuesta HTTP y un identificador de conexión curl.
Podemos configurar varias opciones de rizo. Para obtener una lista completa de opciones, consulte esto . La documentación vinculada es para la API libcurl, pero las opciones no cambian para otros enlaces de idioma.
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)
Si no necesita verificar el certificado. Advertencia: esto es inseguro. Similar a correr
curl -k
ocurl --insecure
.conn.setopt(pycurl.SSL_VERIFYPEER, False) conn.setopt(pycurl.SSL_VERIFYHOST, False)
Llame
cStringIO.write
para almacenar la respuesta HTTP.Cuando realiza una solicitud POST.
post_body = "foobar" conn.setopt(pycurl.POSTFIELDS, post_body)
Realice la solicitud real ahora.
Haga algo basado en el código de respuesta HTTP.
http_code = conn.getinfo(pycurl.HTTP_CODE) if http_code is 200: print response.getvalue()
fuente
Una forma correcta de realizar autenticación básica en Python3
urllib.request
con la validación del certificado.Tenga en cuenta que
certifi
no es obligatorio. Puede usar su paquete de sistema operativo (probablemente * nix solamente) o distribuir el paquete CA de Mozilla usted mismo. O si los hosts con los que se comunica son solo unos pocos, concatene el archivo CA usted mismo de las CA de los hosts, lo que puede reducir el riesgo de un ataque MitM causado por otra CA corrupta.#!/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())
fuente
utilizando solo módulos estándar y sin codificación de encabezado manual
... que parece ser la forma prevista y más portátil
el concepto de Python urllib es agrupar los numerosos atributos de la solicitud en varios gerentes / directores / contextos ... que luego procesan sus partes:
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())
fuente
Basado en la respuesta de @AndrewCox con algunas mejoras menores:
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()
Tenga en cuenta que debe establecer la codificación si usa
bytes
function en lugar deb""
.fuente
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))
Si tiene token, la contraseña debe ser
''
.Esto funciona para mi.
fuente