Подтвердить что ты не робот

HttpURLConnection отлично работает в Android 2.x, но НЕ в 4.1: не обнаружены проблемы аутентификации

У меня есть некоторые типичные коды, которые использовали HttpURLConnection для получения файла с URL-адресом. Они отлично работали в android 1.x и 2.x. Но не удалось в Android 4.1!

Я искал в Интернете, но нашел мало подобной информации. Кто-нибудь, пожалуйста, поможет расследовать эту проблему?

private String mURLStr; 
private HttpURLConnection mHttpConnection;

...

url = new URL(mURLStr);

...

mHttpConnection = (HttpURLConnection) url.openConnection();
mHttpConnection.setDoOutput(true);
mHttpConnection.setRequestMethod("GET");

...

InputStream is = mHttpConnection.getInputStream();

Метод getInputStream генерирует исключение:

08-01 15:56:48.856: W/System.err(13613): java.io.IOException: No authentication challenges found
08-01 15:56:48.856: W/System.err(13613):      at libcore.net.http.HttpURLConnectionImpl.getAuthorizationCredentials(HttpURLConnectionImpl.java:427)
08-01 15:56:48.866: W/System.err(13613):      at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:407)
08-01 15:56:48.866: W/System.err(13613):      at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:356)
08-01 15:56:48.866: W/System.err(13613):      at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:292)
08-01 15:56:48.866: W/System.err(13613):      at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168)
...
4b9b3361

Ответ 1

В настоящее время я сталкиваюсь с той же проблемой. On 4.1 Jelly Bean Я получаю IOException "Нет проблем с проверкой подлинности" при вызове метода getResponseCode() в HttpURLConnection.

Я искал онлайн, чтобы узнать, что изменилось в исходном коде Android, и нашел следующее: 4.0.4 (рабочий): https://bitbucket.org/seandroid/libcore/src/7ecbe081ec95/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java 4.1.1 (не работает): https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java

Как видно из 4.1 JB, метод getAuthorizationCredentials() генерирует исключение IOException. Он анализирует заголовки задач, которые он находит в ответе, используя HeaderParser.parseChallenges(..), если код ответа равен 401 или 407. Если возвращенный список пуст, возникает исключение.

https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HeaderParser.java

В настоящее время мы расследуем то, что именно заставляет этот список быть пустым, но есть подозрение, что наш сервер может использовать realm =... вместо realm = "..." в заголовке запроса. Причиной этой проблемы может быть отсутствие пропущенных кавычек. Мы должны продолжить исследование, если это действительно так, и если мы сможем заставить его работать.

Ответ 2

Per RFC2617:

Ответное сообщение 401 (неавторизованное) используется сервером происхождения    чтобы оспорить авторизацию пользовательского агента. Этот ответ ДОЛЖЕН    включают поле заголовка WWW-Authenticate, содержащее по крайней мере один    вызов, применимый к запрашиваемому ресурсу.

В Android метод HttpURLConnection getResponseCode() вызывает java.io.IOException: No authentication challenges found, когда сервер возвращает либо код состояния 401 Unauthorized, либо 407 Proxy Authentication Required без WWW-аутентификации набор заголовков.

Если у вас есть API-интерфейс на стороне сервера, вы можете исправить его, добавив требуемый заголовок WWW-Authenticate при возврате 401 или 407. В моем случае я исправил его на PHP следующим образом:

header('WWW-Authenticate: OAuth realm="users"');
header('HTTP/1.1 401 Unauthorized');

Ответ 3

У меня та же проблема. Я нашел это обходное решение, но он не работает на Android 2. На желе Bean он отлично работает. Просто используйте getErrorStream() вместо getInputStream().

try
{
    responseStream = new BufferedInputStream(connection.getInputStream());
}
catch(IOException e)
{
    responseStream = new BufferedInputStream(connection.getErrorStream());
}

Ответ 4

Заголовок

Я исправил проблему для Желе bean. Для приведенного выше сценария используйте приведенный ниже код.

DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(userName,userPass));
HttpGet request = new HttpGet();
request.addHeader("Accept", "application/xml");
request.setURI(new URI(service));
HttpResponse response = client.execute(request);

у вас есть правильный ответ по мере необходимости.

Ответ 5

У меня возникла аналогичная проблема с веб-службой, которая требовала, чтобы файлы cookie работали корректно. Очевидно, что Jelly Bean автоматически не создает хранилище cookie по умолчанию (в отличие от предыдущих версий), поэтому служба не смогла найти мой сеанс и каждый раз, когда я пытался получить доступ к ней, добавлял 401. Добавление следующих строк кода в мою инициализацию приложения устранило проблему:

// enable VM-wide cookie support for HttpUrlConnection
// see http://developer.android.com/reference/java/net/HttpURLConnection.html for details
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

Ответ 7

Проверьте, возвращает ли ваш сервер Error 401 - Not Authorised. Я считаю, что код Android видит этот ответ и полагает, что он предназначен для предоставления сведений об аутентификации. В моем случае я просто предоставлял неверный токен моему серверу.

Ответ 8

Существует одно решение

В вашем коде Удалите это

HttpConnection.setDoOutput(true);

Он будет работать на ICS или Jelly Bean

Ответ 9

Решение, которое я использовал для этого (я использую библиотеку Android Volley), должно было использовать Квадратная библиотека OkHttp. Их реализация правильно обрабатывает эту проблему и вернет 401, как ожидалось.