Actualización: basado en el comentario de Lee, decidí condensar mi código en un script realmente simple y ejecutarlo desde la línea de comando:
import urllib2
import sys
username = sys.argv[1]
password = sys.argv[2]
url = sys.argv[3]
print("calling %s with %s:%s\n" % (url, username, password))
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, url, username, password)
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPBasicAuthHandler(passman)))
req = urllib2.Request(url)
f = urllib2.urlopen(req)
data = f.read()
print(data)
Desafortunadamente, todavía no generará el Authorization
encabezado (según Wireshark) :(
Tengo un problema para enviar AUTH básica a través de urllib2. Eché un vistazo a este artículo y seguí el ejemplo. Mi código:
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, "api.foursquare.com", username, password)
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPBasicAuthHandler(passman)))
req = urllib2.Request("http://api.foursquare.com/v1/user")
f = urllib2.urlopen(req)
data = f.read()
Veo lo siguiente en Wire a través de wirehark:
GET /v1/user HTTP/1.1
Host: api.foursquare.com
Connection: close
Accept-Encoding: gzip
User-Agent: Python-urllib/2.5
Puede ver que la autorización no se envía, en comparación con cuando envío una solicitud a través de curl: curl -u user:password http://api.foursquare.com/v1/user
GET /v1/user HTTP/1.1
Authorization: Basic =SNIP=
User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8k zlib/1.2.3
Host: api.foursquare.com
Accept: */*
Por alguna razón, mi código parece no enviar la autenticación. ¿Alguien ve lo que me estoy perdiendo?
Gracias
-Simón
python
authentication
urllib2
Simón
fuente
fuente
'WWW-Authenticate'
encabezado. Puede verificar esto usandotry: urllib2.urlopen(req) except urllib2.HTTPError, e: print e.headers
Ver esta respuesta de publicación SO .Respuestas:
El problema podría ser que las bibliotecas de Python, según HTTP-Standard, primero envían una solicitud no autenticada, y luego, solo si se responde con un reintento 401, se envían las credenciales correctas. Si los servidores de Foursquare no realizan una "autenticación totalmente estándar", las bibliotecas no funcionarán.
Intente usar encabezados para realizar la autenticación:
import urllib2, base64 request = urllib2.Request("http://api.foursquare.com/v1/user") base64string = base64.b64encode('%s:%s' % (username, password)) request.add_header("Authorization", "Basic %s" % base64string) result = urllib2.urlopen(request)
Tuve el mismo problema que tú y encontré la solución en este hilo: http://forums.shopify.com/categories/9/posts/27662
fuente
base64.b64encode
lugar debase64.encodestring
y luego no es necesario reemplazar la nueva línea.(copiar y pegar / adaptado de https://stackoverflow.com/a/24048772/1733117 ).
Primero puede crear una subclase
urllib2.BaseHandler
ourllib2.HTTPBasicAuthHandler
, e implementarlohttp_request
para que cada solicitud tenga elAuthorization
encabezado apropiado .import urllib2 import base64 class PreemptiveBasicAuthHandler(urllib2.HTTPBasicAuthHandler): '''Preemptive basic auth. Instead of waiting for a 403 to then retry with the credentials, send the credentials if the url is handled by the password manager. Note: please use realm=None when calling add_password.''' def http_request(self, req): url = req.get_full_url() realm = None # this is very similar to the code from retry_http_basic_auth() # but returns a request object. user, pw = self.passwd.find_user_password(realm, url) if pw: raw = "%s:%s" % (user, pw) auth = 'Basic %s' % base64.b64encode(raw).strip() req.add_unredirected_header(self.auth_header, auth) return req https_request = http_request
Entonces, si eres vago como yo, instala el controlador globalmente
api_url = "http://api.foursquare.com/" api_username = "johndoe" api_password = "some-cryptic-value" auth_handler = PreemptiveBasicAuthHandler() auth_handler.add_password( realm=None, # default realm. uri=api_url, user=api_username, passwd=api_password) opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener)
fuente
Esto es lo que estoy usando para lidiar con un problema similar que encontré al intentar acceder a la API de MailChimp. Esto hace lo mismo, simplemente formateado mejor.
import urllib2 import base64 chimpConfig = { "headers" : { "Content-Type": "application/json", "Authorization": "Basic " + base64.encodestring("hayden:MYSECRETAPIKEY").replace('\n', '') }, "url": 'https://us12.api.mailchimp.com/3.0/'} #perform authentication datas = None request = urllib2.Request(chimpConfig["url"], datas, chimpConfig["headers"]) result = urllib2.urlopen(request)
fuente
El segundo parámetro debe ser un URI, no un nombre de dominio. es decir
passman = urllib2.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None, "http://api.foursquare.com/", username, password)
fuente
http://api.foursquare.com
,api.foursquare.com
,http://api.foursquare.com/v1/
, pero que no parece resolver el problema.'WWW-Authenticate'
; ver esta respuesta de la publicación SO .Sugeriría que la solución actual es usar mi paquete urllib2_prior_auth que resuelve esto bastante bien (trabajo en la inclusión en el estándar lib.
fuente
urllib2.urlopen('http://USER:[email protected]/path/')
urllib2
?