Android: HttpsUrlConnection с Authenticator для базовой аутентификации выполняет итерации вечно, когда пароль неверен (в ответе 401) - PullRequest
11 голосов
/ 18 октября 2011

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

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

Когда я получаю доступ к моей веб-службе, соединение вызывает мой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    

Ответы [ 2 ]

5 голосов
/ 29 ноября 2012

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

            ...

    }
}
3 голосов
/ 29 августа 2012

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

В итоге мне пришлось использовать HttpClient вместо.

...