9

Estoy tratando de descargar una página protegida con autenticación básica usando urllib2. Estoy usando Python 2.7 pero también lo probé en otra computadora con Python 2.5 y encontré exactamente el mismo comportamiento. Seguí el ejemplo dado en this guide tan de cerca como pude y aquí está el código que produje:Autenticación HTTP básica no parece funcionar con urllib2 en python

import urllib2 

passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
passman.add_password(None, "http://authenticationsite.com/', "protected", "password") 
authhandler = urllib2.HTTPBasicAuthHandler(passman) 
opener = urllib2.build_opener(authhandler) 

f = opener.open("http://authenticationsite.com/content.html") 
print f.read() 
f.close() 

Desafortunadamente el servidor no es mía, así que no puedo compartir los detalles; Los cambié arriba y abajo. Cuando lo ejecuto me sale el siguiente Rastreo:

File 
"/usr/lib/python2.7/urllib2.py", line 
397, in open 
response = meth(req, response) File "/usr/lib/python2.7/urllib2.py", 
line 510, in http_response 
'http', request, response, code, msg, hdrs) File 
"/usr/lib/python2.7/urllib2.py", line 
435, in error 
return self._call_chain(*args) File "/usr/lib/python2.7/urllib2.py", 
line 369, in _call_chain 
result = func(*args) File "/usr/lib/python2.7/urllib2.py", line 
518, in http_error_default 
raise HTTPError(req.get_full_url(), code, 
msg, hdrs, fp) urllib2.HTTPError: HTTP 
Error 401: Authorization Required 

Ahora, la parte interesante es cuando puedo monitorear el tráfico TCP en el ordenador utilizando ngrep:

ngrep host 74.125.224.49 interface: 
wlan0 (192.168.1.0/255.255.255.0) 
filter: (ip) and (host 74.125.224.49 
) 
#### T 192.168.1.74:34366 -74.125.224.49:80 [AP] GET /content.html 
HTTP/1.1..Accept-Encoding: 
identity..Host: 
authenticationsite.com..Connection: 
close..User-Agent: 
Python-urllib/2.7.... 

## T 74.125.224.49:80 -192.168.1.74:34366 [AP] HTTP/1.1 401 Authorization Required..Date: Sun, 27 
Feb 2011 03:39:31 GMT..Server: 
Apache/2.2.3 (Red 
Hat)..WWW-Authenticate: Digest 
realm="protected", 
nonce="6NSgTzudBAA=ac585d1f7ae0632c4b90324aff5e39e0f1fc25 
05", algorithm=MD5, 
qop="auth"..Content-Length: 
486..Connection: close..Content-Type: text/html; 
charset=iso-8859-1....<!DOCTYPE HTML 
PUBLIC "-//IETF//DTD HTML 
2.0//EN">.<html><head>.<title>401 Authorization 
Required</title>.</head><body>.<h1>Authorization 
Required</h1>.<p>This server could not 
verify that you.are authorized to 
access the document.requested. Either 
you supplied the wrong.credentials 
(e.g., badpassword), or 
your.browser doesn't understand how to 
supply.the credentials 
required.</p>.<hr>.<address>Apache/2.2.3 
(Red Hat) Server at 
authenticationsite.com Port 
80</address>.</body></html>. 

#### 

Parece como si urllib2 es tirar que excepción sin siquiera intentar proporcionar las credenciales después de obtener el error inicial 401.

Para comparion, aquí está la salida de ngrep cuando lo haga la autenticación en un navegador web en su lugar:

ngrep host 74.125.224.49 interface: 
wlan0 (192.168.1.0/255.255.255.0) 
filter: (ip) and (host 74.125.224.49 
) 
#### T 192.168.1.74:36102 -74.125.224.49:80 [AP] GET /content.html HTTP/1.1..Host: 
authenticationsite.com..User-Agent: 
Mozilla/5.0 (X11; U; Linux i686; 
en-US; rv:1.9.2.12) Gecko/20101027 
Firefox/3.6.12..Accept: text 
/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8..Accept-Language: 
en-us,en;q=0.5..Accept-Encoding: 
gzip,deflate..Accept-Charset: 
ISO-8859-1,utf-8;q=0.7,*;q=0.7..Keep-Alive: 
115..Connection: keep- alive.... 
## T 74.125.224.49:80 -192.168.1.74:36102 [AP] HTTP/1.1 401 Authorization Required..Date: Sun, 27 
Feb 2011 03:43:42 GMT..Server: 
Apache/2.2.3 (Red 
Hat)..WWW-Authenticate: Digest 
realm="protected", 
nonce="rKCfXjudBAA=0c1111321169e30f689520321dbcce37a1876b 
be", algorithm=MD5, 
qop="auth"..Content-Length: 
486..Connection: close..Content-Type: text/html; 
charset=iso-8859-1....<!DOCTYPE HTML 
PUBLIC "-//IETF//DTD HTML 
2.0//EN">.<html><head>.<title>401 Authorization 
Required</title>.</head><body>.<h1>Authorization 
Required</h1>.<p>This server could not 
verify that you.are authorized to 
access the document.requested. Either 
you supplied the wrong.credentials 
(e.g., badpassword), or 
your.browser doesn't understand how to 
supply.the credentials 
required.</p>.<hr>.<address>Apache/2.2.3 
(Red Hat) Server at 
authenticationsite.com Port 
80</address>.</body></html>. 

######### T 192.168.1.74:36103 -74.125.224.49:80 [AP] GET /content.html HTTP/1.1..Host: 
authenticationsite.com..User-Agent: 
Mozilla/5.0 (X11; U; Linux i686; 
en-US; rv:1.9.2.12) Gecko/20101027 
Firefox/3.6.12..Accept: text 
/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8..Accept-Language: 
en-us,en;q=0.5..Accept-Encoding: 
gzip,deflate..Accept-Charset: 
ISO-8859-1,utf-8;q=0.7,*;q=0.7..Keep-Alive: 
115..Connection: keep- alive..Authorization: Digest 
username="protected", 
realm="protected", 
nonce="rKCfXjudBAA=0c1111199162342689520550dbcce37a1876bbe", 
uri="/content.html", algorithm= MD5, 
response="3b65dadaa00e1d6a1892ffff49f9f325", 
qop=auth, nc=00000001, 
cnonce="7636125b7fde3d1b".... 

## 

y luego siguió con el contenido del sitio.

He estado jugando con esto por un tiempo y no puedo entender lo que estoy haciendo mal. ¡Estaría muy agradecido si alguien puede ayudarme!

Respuesta

9

Creo que eso es causado por esto:

WWW-Authenticate: Digest 

Parece que los recursos se autentica con el Digesto más que básico. Lo que significa que debe usar urllib2.HTTPDigestAuthHandler en su lugar.

El código podría ser

import urllib2 

passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
passman.add_password(None, "http://authenticationsite.com/", "protected", "password") 

# use HTTPDigestAuthHandler instead here 
authhandler = urllib2.HTTPDigestAuthHandler(passman) 
opener = urllib2.build_opener(authhandler) 

res = opener.open("http://authenticationsite.com/content.html") 
print res.read() 
res.close() 
+0

¡Gracias, estabas en lo cierto! ¡Realmente aprecio tu ayuda! – foob

+0

Tengo un problema al eliminar la URL de un sitio de mi secuencia de comandos python, que extraerá todos los sitios que contienen los pdfs. Estoy trabajando detrás de un proxy que solicita un nombre de usuario y pwd cuando abro el navegador por primera vez. Puedo ver el sitio y descargar archivos PDF desde el sitio usando el navegador. Sin embargo, no puedo hacerlo a través del código en Python. El error que estoy enfrentando es: "urllib.error.HTTPError: HTTP Error 401: Se requiere autorización" estoy consiguiendo el error: "AbstractDigestAuthHandler no es compatible con el siguiente esquema: 'negociar'" Me estoy perdiendo algo? – Bonson

-1
import urllib2 
# Create an OpenerDirector with support for Basic HTTP Authentication... 
auth_handler = urllib2.HTTPBasicAuthHandler() 
auth_handler.add_password(realm='PDQ Application', 
          uri='https://mahler:8092/site-updates.py', 
          user='klem', 
          passwd='kadidd!ehopper') 
opener = urllib2.build_opener(auth_handler) 
# ...and install it globally so it can be used with urlopen. 
urllib2.install_opener(opener) 
urllib2.urlopen('http://www.example.com/login.html') 

- http://docs.python.org/library/urllib2.html#examples

+0

Esto es esencialmente lo que ya estaba haciendo. Como señaló Victor Lin en la otra respuesta, el problema era que el servidor en realidad utiliza Autenticación implícita en lugar de Autenticación básica. – foob

0

usted tiene que utilizar el módulo NTLM pitón para esto:

de importación ntlm HTTPNtlmAuthHandler

importación urllib2

user = "su_nombre_de_usuario"

contraseña = "your_Passwrd"

Passman = urllib2.HTTPPasswordMgrWithDefaultRealm()

passman.add_password (Ninguno, "http://your_Home_location/", de usuario, contraseña)

auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler (Passman)

abridor = urllib2.build_opener (auth_NTLM)

urllib2.install_opener (abridor)

url = "http://Your_home_location/sub_locations"

respuesta = urllib2.urlopen (url)

cabeceras = response.info()

de impresión ("encabezados: {}" formato. (cabeceras))

cuerpo = response.read()

de impresión ("respuesta:" + cuerpo)

Cuestiones relacionadas