Mise à jour: sur la base du commentaire de Lee, j'ai décidé de condenser mon code en un script très simple et de l'exécuter à partir de la ligne de commande:
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)
Malheureusement, il ne générera toujours pas l'en-tête Authorization
(selon Wireshark) :(
J'ai un problème pour envoyer AUTH de base sur urllib2. J'ai jeté un œil à cet article et suivi l'exemple. Mon code:
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()
Je vois ce qui suit sur le Wire via Wirehark:
GET /v1/user HTTP/1.1
Host: api.foursquare.com
Connection: close
Accept-Encoding: gzip
User-Agent: Python-urllib/2.5
Vous pouvez voir que l’autorisation n’est pas envoyée, c’est-à-dire quand j’envoie une demande via 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: */*
Pour une raison quelconque, mon code ne semble pas envoyer d'authentification. Quelqu'un voit-il ce qu'il me manque?
merci
-Simon
Le problème pourrait être que les bibliothèques Python, conformément à la norme HTTP, envoient d’abord une demande non authentifiée, puis que si les réponses sont renvoyées avec une nouvelle tentative 401, les informations d’identité correctes sont envoyées. Si les serveurs Foursquare ne faites pas "authentification totalement standard" alors les bibliothèques ne fonctionneront pas.
Essayez d'utiliser des en-têtes pour effectuer l'authentification:
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)
Avait le même problème que vous et a trouvé la solution de ce fil de discussion: http://forums.shopify.com/categories/9/posts/27662
Voici ce que j'utilise pour traiter un problème similaire que j'ai rencontré lors de la tentative d'accès à l'API de MailChimp. Cela fait la même chose, juste formaté plus agréable.
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)
(copier-coller/adapté de https://stackoverflow.com/a/24048772/1733117 ).
D'abord, vous pouvez sous-classe urllib2.BaseHandler
ou urllib2.HTTPBasicAuthHandler
, et implémenter http_request
afin que chaque demande ait l'en-tête Authorization
approprié.
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
Ensuite, si vous êtes paresseux comme moi, installez le gestionnaire globalement
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)
Le deuxième paramètre doit être un URI et non un nom de domaine. c'est à dire.
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, "http://api.foursquare.com/", username, password)
Je suggérerais que la solution actuelle consiste à utiliser mon paquetage rllib2_prior_auth qui résout ce joli problème (je travaille sur inclusion à la bibliothèque standard.