2011-10-18 11 views
11

मैं एक Authenticator का उपयोग कर और एक डिफ़ॉल्ट Authenticator वस्तु इस तरह की स्थापना करके मूल प्रमाणीकरण के साथ एक HttpsUrlConnection उपयोग कर रहा हूँ:एंड्रॉयड: बेसिक प्रमाणीकरण दोहराता के लिए प्रमाणक से HttpsURLConnection हमेशा के लिए जब पासवर्ड गलत है (401 प्रतिक्रिया पर)

Authenticator.setDefault(new Authenticator() { 
    protected PasswordAuthentication getPasswordAuthentication() { 
     return new PasswordAuthentication("user", "userpass" 
      .toCharArray()); 
    } 
}); 

जब मैं अपनी वेब-सेवा तक पहुंचता हूं तो कनेक्शन प्रमाण पत्र प्राप्त करने के लिए मेरे getPasswordAuthentication() विधि को कॉल करता है और इसे वेब-सर्वर पर भेजता है। जब तक पासवर्ड सही होता है तब तक यह ठीक काम करता है। :)

हालांकि, ऐसा हुआ कि किसी ने वेब-सर्वर पर मूल प्रमाणीकरण पासवर्ड बदल दिया और फिर मेरा अनुरोध वापस नहीं आया।

मैंने इसे डीबग किया और क्या होता है कि getInputStream() पर मेरा कॉल कभी वापस नहीं आता है। HttpsUrlConnection को 401 प्रतिक्रिया मिलती है और फिर भी वही प्रमाण-पत्र प्राप्त करके आंतरिक रूप से प्रतिक्रिया देती है। लेकिन चूंकि मैंने केवल एक उपयोगकर्ता और पासवर्ड प्रदान किया है, यह फिर से विफल हो जाएगा (और फिर ...)।

तो मेरा सवाल यह है कि: मैं इसे कैसे रोक सकता हूं और गलत पासवर्ड पर प्रतिक्रिया करने के लिए एक हुक कहां है (एक 401 प्रतिक्रिया)। इसलिए मैं एक उचित त्रुटि संदेश दिखा सकता हूं और अनुरोध रद्द कर सकता हूं?

1: MyOwnHttpConnection$3.getPasswordAuthentication() line: 99 
2: Authenticator.requestPasswordAuthentication(InetAddress, int, String, String, String) line: 162 
3: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).getAuthorizationCredentials(String) line: 1205 
4: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).processAuthHeader(String, String) line: 1178 
5: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).processResponseHeaders() line: 1118  
6: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).retrieveResponse() line: 1044 
7: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).getInputStream() line: 523 
8: HttpsURLConnectionImpl.getInputStream() line: 283  
+1

संभव डुप्लिकेट [एंड्रॉयड, HttpURLConnection और बुरे साख से निपटने] (http://stackoverflow.com/questions/7061211/android-httpurlconnection-and-handling- खराब प्रमाण-पत्र) – yanchenko

उत्तर

5

मैं एक MyRequest वर्ग में दूर सार संक्षेप अनुरोध/प्रतिक्रिया तर्क इस समस्या का समाधान। यह मुझे एक अनुरोध-स्कोप्ड वैरिएबल प्राप्त करने की अनुमति देता है जो मेरे Authenticator को बता सकता है कि क्या उसे निर्दिष्ट उपयोगकर्ता नाम और पासवर्ड का उपयोग करके अनुरोध करना चाहिए, या फिर इसे पुनः प्रयास करना बंद कर देना चाहिए (null लौटकर)। यह कुछ हद तक निम्नलिखित की तरह लग रहा है (यह स्यूडोकोड पर विचार)

public class MyRequest 
{ 
    private boolean alreadyTriedAuthenticating = false; 
    private URL url; 

    ... 

    public void send() 
    { 
     HttpUrlConnection connection = (HttpUrlConnection) url.openConnection(); 
     Authenticator.setDefault(new Authenticator() { 
      protected PasswordAuthentication getPasswordAuthentication() { 
       if (!alreadyTriedAuthenticating) 
       { 
        alreadyTriedAuthenticating = true; 
        return new PasswordAuthentication(username, password.toCharArray()); 
       } 
       else 
       { 
        return null; 
       } 
      } 
      InputStream in = new BufferedInputStream(connection.getInputStream()); 

      ... 

    } 
} 
की
+0

बिल्कुल! इस पर ध्यान दिलाने के लिए धन्यवाद! यह http://code.google.com/p/android/issues/detail?id=7058 बंद करने वाले उत्तर के अनुसार प्रमाणीकरणकर्ता को * नए * क्रेडेंशियल्स के सेट के लिए उपयोगकर्ता से पूछना चाहिए क्योंकि पहले आपूर्ति किए गए काम नहीं किया यदि प्रामाणिकता केवल प्री-सेट क्रेडिट का उपयोग कर रही है तो उसे ट्रैक का पिछला प्रयास विफल रखने की आवश्यकता है। – Maks

3

मुझे लगता है मैं यह करने के लिए उचित जवाब पता था, क्योंकि मैं ठीक उसी समस्या में पड़ गए इच्छा:

यहाँ तरीकों कि HttpsUrlConnection पर repeatingly कहा जाता है की स्टैक ट्रेस के एक उद्धरण है। मुझे प्रमाणीकरण त्रुटि को संभालने का कोई तरीका नहीं मिला, या यहां तक ​​कि इसके बारे में अधिसूचित भी हो गया।

मैं इसके बजाय HttpClient का उपयोग करने के लिए समाप्त हुआ।

HttpClient client = new DefaultHttpClient(); 
HttpGet get = new HttpGet(loginUrl); 
String authString = (userName+":"+password); 
get.addHeader("Authorization", "Basic " + 
    Base64.encodeToString(authString.getBytes(),Base64.NO_WRAP)); 
HttpResponse response = client.execute(get); 

BufferedReader r = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 
+0

हालांकि एक अच्छा विकल्प माना जाता है। मैंने अपने कोड में कुछ भी नहीं बदला है। मैं केवल यह सुनिश्चित करता हूं कि कोई मुझे सूचित किए बिना पासवर्ड बदलता है ... :-) – Jens