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) ... 

В настоящее время я сталкиваюсь с той же проблемой. На 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

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

В RFC2617 :

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

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

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

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

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

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

заголовок

Я исправил проблему для Jelly 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); 

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

Я столкнулся с аналогичной проблемой с веб-службой, которая требовала, чтобы cookies работали правильно. Очевидно, 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); 

При использовании обычной проверки подлинности и не вызывающей setDoOutput (true) у нас все еще была эта проблема:

Вот решение:

Базовая проверка подлинности HTTP на Android Jelly Bean 4.1 с использованием HttpURLConnection

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

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

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

HttpConnection.setDoOutput (истина);

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

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

  • Аутентификация на основе токенов в ядре ASP.NET (обновлена)
  • Вставить фид активности общедоступной страницы Facebook, не заставляя пользователя входить в систему / разрешать
  • Аутентификация веб-API ASP.NET
  • Добавить Keypair в существующий экземпляр EC2
  • ASP.NET Core 2.0 отключает автоматическую задачу
  • LDAP: код ошибки 49 - 80090308: LdapErr: DSID-0C0903A9, комментарий: Ошибка AcceptSecurityContext, данные 52e, v1db1
  • Вложение свойств по атрибутам
  • Микширование форм с помощью проверки подлинности Windows
  • Корневой доступ MySQL от всех хостов
  • Лучшие практики SPA для аутентификации и управления сеансами
  • Настройка Spring Security 3.x для создания нескольких точек входа
  • Давайте будем гением компьютера.