पायथन urllib2 मूल प्रामाणिक समस्या


81

अपडेट: ली की टिप्पणी के आधार पर मैंने अपने कोड को एक बहुत ही सरल स्क्रिप्ट में सम्मिलित करने और इसे कमांड लाइन से चलाने का निर्णय लिया:

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)

दुर्भाग्य से यह अभी भी Authorizationहेडर (प्रति विंडसर) उत्पन्न नहीं करेगा :(

मुझे urllib2 पर बुनियादी AUTH भेजने में समस्या हो रही है। मैंने इस लेख पर एक नज़र डाली , और उदाहरण का अनुसरण किया। मेरा कोड:

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()

मैं तार पर तारों के माध्यम से निम्नलिखित देख रहा हूँ:

GET /v1/user HTTP/1.1
Host: api.foursquare.com
Connection: close
Accept-Encoding: gzip
User-Agent: Python-urllib/2.5 

आप देख सकते हैं कि प्राधिकरण भेजा नहीं गया है, बनाम जब मैं कर्ल के माध्यम से अनुरोध भेजता हूं: 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: */*

किसी कारण से मेरा कोड प्रमाणीकरण नहीं भेजता है - कोई भी देखता है कि मुझे क्या याद आ रहा है?

धन्यवाद

-simon


1
मुझे आश्चर्य है कि अगर समस्या यह है कि साइट 'WWW-Authenticate'हेडर नहीं लौटा रही है । आप try: urllib2.urlopen(req) except urllib2.HTTPError, e: print e.headers इस एसओ पोस्ट के जवाब को देखकर इसका उपयोग कर सकते हैं ।
मार्क मिकोफ़्स्की

जवाबों:


199

समस्या यह हो सकती है कि HTTP-Standard के अनुसार, Python पुस्तकालयों को पहले एक बिना मांगे अनुरोध भेजा जाए, और उसके बाद ही यदि उसे 401 पुनर्प्रयास के साथ उत्तर दिया जाए, तो सही क्रेडेंशियल भेजे गए हैं। यदि Foursquare सर्वर "पूरी तरह से मानक प्रमाणीकरण" नहीं करते हैं, तो पुस्तकालय काम नहीं करेंगे।

प्रमाणीकरण करने के लिए शीर्ष लेख का उपयोग करने का प्रयास करें:

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)

आप के रूप में एक ही समस्या थी और इस धागे से समाधान पाया: http://forums.shopify.com/categories/9/posts/27662


HTTP एरर 505: HTTP वर्जन समर्थित नहीं है;
डैनियल मैग्नसन

पेपैल प्रमाणीकरण के साथ काम करता है (साथ ही access_token प्राप्त करने के लिए)। बहुत बहुत धन्यवाद, दोस्त!
डेरशोडन

3
ध्यान दें कि आप base64.b64encodeइसके बजाय सरल कॉल कर सकते हैं base64.encodestringऔर फिर आपको नई लाइन को बदलने की आवश्यकता नहीं है।
ट्रे स्टट

धन्यवाद @TreyStout, मैंने आपके सुझाव को शामिल करने के लिए समाधान संपादित किया।
yayitswei

यहाँ भी ऐसी ही समस्या है। प्राधिकृत पृष्ठ की ब्राउज़र सामग्री भरी हुई है और यदि मैं बटन को रद्द करता हूँ तो मैं पासवर्ड पृष्ठ की सामग्री देख सकता हूँ
Mostafa

5

(कॉपी-पेस्ट / https://stackoverflow.com/a/24048772/1733117 से अनुकूलित )।

पहले आप उप-लिंक कर सकते हैं urllib2.BaseHandlerया urllib2.HTTPBasicAuthHandlerलागू कर सकते हैं , http_requestताकि प्रत्येक अनुरोध में उपयुक्त Authorizationहेडर हो।

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

फिर यदि आप मेरी तरह आलसी हैं, तो विश्व स्तर पर हैंडलर स्थापित करें

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)

5

यहाँ मैं उसी तरह की समस्या से निपटने के लिए उपयोग कर रहा हूँ जो मैंने MailChimp के API तक पहुँचने की कोशिश करते समय सामना की थी। यह एक ही काम करता है, बस स्वरूपित अच्छे।

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)

4

दूसरा पैरामीटर एक URI होना चाहिए, एक डोमेन नाम नहीं। अर्थात

passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, "http://api.foursquare.com/", username, password)

1
धन्यवाद - मैं मैं करने की कोशिश की है कि विभिन्न संयोजनों की संख्या में उल्लेख किया जाना चाहिए था http://api.foursquare.com, api.foursquare.com, http://api.foursquare.com/v1/, लेकिन उस समस्या को हल करने प्रतीत नहीं होता।
साइमन

मैंने यहां केवल एक स्थानीय सर्वर के खिलाफ यह कोशिश की थी, जिसमें मूलभूत स्रोत की आवश्यकता होती है और add_password में URL के साथ यह ठीक काम करता है। इसलिए मैं सुझाव दूंगा कि कुछ और ही है।
ली

यह तभी काम करेगा जब http प्रतिक्रिया में कोड 401 अनधिकृत और हेडर हो 'WWW-Authenticate'; देखना यह इतना पोस्ट जवाब
मार्क मिकोफ़्स्की

0

मेरा सुझाव है कि वर्तमान समाधान मेरे पैकेज urllib2_prior_auth का उपयोग करना है जो इस सुंदर तरीके से हल करता है (मैं मानक देयता में शामिल करने पर काम करता हूं ।


विल इसे urllib2.urlopen('http://USER:PASS@example.com/path/')
यूरेल

यह एक और समस्या है। क्या आप निश्चित हैं कि यह मानक के साथ काम नहीं करता है urllib2?
20'16
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.