2011-10-18 21 views
11

Tôi đang sử dụng một HttpsUrlConnection với Basic Authentication bằng cách sử dụng một Authenticator và thiết lập một đối tượng mặc định Authenticator như thế này:Android: HttpsUrlConnection với Authenticator cho lặp Basic Authentication mãi mãi khi mật khẩu là sai (trên 401 câu trả lời)

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

Khi tôi truy cập dịch vụ web của mình, kết nối gọi phương thức getPasswordAuthentication() của tôi để nhận thông tin xác thực và gửi thông tin này tới máy chủ web. Điều này làm việc hoàn toàn miễn là mật khẩu là chính xác. :)

Tuy nhiên, nó chỉ xảy ra khi ai đó thay đổi mật khẩu xác thực cơ bản trên máy chủ web và sau đó yêu cầu của tôi không trả lại.

Tôi đã sửa lỗi và điều xảy ra là lệnh gọi của tôi tới getInputStream() không bao giờ trả lại. Các HttpsUrlConnection không nhận được một phản ứng 401 và phản ứng với nội bộ này bằng cách nhận được các thông tin tương tự một lần nữa. Nhưng kể từ khi tôi chỉ cung cấp một người dùng và mật khẩu này sẽ thất bại một lần nữa (và một lần nữa ...). Vì vậy, câu hỏi của tôi là: Làm thế nào tôi có thể ngăn chặn điều này và nơi có móc để phản ứng với một mật khẩu sai (resp. Đáp 401 phản ứng) để tôi có thể hiển thị một thông báo lỗi thích hợp và hủy bỏ yêu cầu?

Dưới đây là một trích lục đống dấu vết của các phương pháp được gọi là repeatingly trên HttpsUrlConnection:

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

có thể trùng lặp với [Android, HttpURLConnection và xử lý thông tin xác thực xấu] (http://stackoverflow.com/questions/7061211/android-httpurlconnection-and-handling- xấu-credentials) – yanchenko

Trả lời

5

Tôi đã giải quyết vấn đề này bằng cách tóm tắt logic yêu cầu/phản hồi thành lớp học MyRequest. Điều này cho phép tôi có biến số phạm vi yêu cầu có thể cho biết Authenticator của mình cho dù có nên yêu cầu bằng tên người dùng và mật khẩu được chỉ định hay không hoặc liệu nó có nên ngừng thử lại hay không (bằng cách trả lại null). Dường như phần sau (xem mã giả này)

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

chính xác! cảm ơn vì đã chỉ ra điều này! theo câu trả lời đã đóng http://code.google.com/p/android/issues/detail?id=7058 Authenticator được yêu cầu yêu cầu người dùng cho một tập hợp thông tin * mới * vì những thông tin được cung cấp trước đó không hoạt động. Nếu người xác thực chỉ sử dụng tín dụng được đặt trước thì nó cần phải theo dõi nó, nỗ lực trước đó đã thất bại. – Maks

3

Tôi ước gì tôi biết câu trả lời thích hợp để này, bởi vì tôi chạy vào cùng một vấn đề chính xác. Tôi không thể tìm cách xử lý lỗi xác thực hoặc thậm chí được thông báo về nó.

Tôi đã phải sử dụng HttpClient để thay thế.

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

Dường như là một lựa chọn tốt mặc dù. Tôi đã không thay đổi bất cứ điều gì trong mã của tôi. Tôi chỉ đảm bảo không ai thay đổi mật khẩu mà không thông báo cho tôi ... :-) – Jens

Các vấn đề liên quan