Android: HttpsUrlConnection с аутентификатором для базовой проверки подлинности итерации навсегда, когда пароль неверен (на ответ 401)

Я использую HttpsUrlConnection с базовой аутентификацией, используя Authenticator и устанавливая объект Authenticator умолчанию следующим образом:

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

Когда я обращаюсь к своему веб-сервису, соединение вызывает мой getPasswordAuthentication() для получения учетных данных и getPasswordAuthentication() его на веб-сервер. Это работает отлично, если пароль правильный. 🙂

Однако только что случилось, что кто-то изменил базовый пароль аутентификации на веб-сервере, а затем мой запрос не вернулся.

Я отлаживал его, и происходит то, что мой вызов getInputStream() никогда не возвращается. HttpsUrlConnection получает ответ 401 и реагирует на это внутренне, снова получая те же учетные данные. Но поскольку я предоставил только одного пользователя и пароль, это снова не сработает (и снова …).

Поэтому мой вопрос: как я могу предотвратить это и где есть крючок, чтобы реагировать на неправильный пароль (соответственно ответ 401), поэтому я могу показать соответствующее сообщение об ошибке и отменить запрос?

Вот выдержка из трассировки стека методов, которые повторяются на 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 

Solutions Collecting From Web of "Android: HttpsUrlConnection с аутентификатором для базовой проверки подлинности итерации навсегда, когда пароль неверен (на ответ 401)"

Я решил эту проблему, абстрагируя логику запроса / ответа от класса 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()); ... } } 

Хотел бы я знать правильный ответ на этот вопрос, потому что я столкнулся с одной и той же проблемой. Я не мог найти способ справиться с ошибкой аутентификации или даже получить уведомление об этом.

В итоге мне пришлось использовать 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()));