Ошибка андроида - волейбола
Я пытаюсь работать с некоторым устаревшим кодом и сталкивался с проблемой при использовании volley.
Я пытаюсь добраться до api, что наш главный сайт имеет, и он отлично работает для одной учетной записи, но не другой. Я пытаюсь разобраться, какие различия могут быть в URL-адресах запроса, а также о том, что возвращается в ответ, но я не могу найти способ в коде волейбола напечатать это в журнале.
Ошибка, которую я получаю,
com.android.volley.NoConnectionError: java.io.IOException: No authentication challenges found
Я читал, что это может быть связано с ответом 401, но я действительно не знаю, что это значит или, по крайней мере, как это доказать/проверить. Я действительно смущен тем, что он работает для одного аккаунта, а не другого.
URL-адрес немного отличается, как и для нашего сайта в Великобритании, а другой наш AM, но кроме этого нет никакой разницы.
Спасибо
Ответы
Ответ 1
Эта ошибка возникает, потому что сервер отправляет 401 (неавторизованный), но не дает "WWW-Authenticate", который является подсказкой для клиента, что делать дальше. Заголовок "WWW-Authenticate" сообщает клиенту, какой тип аутентификации необходим (Basic или Digest). Обычно это не очень полезно в безгласных http-клиентах, но это то, как определяется стандарт. Ошибка возникает из-за того, что lib пытается проанализировать заголовок "WWW-Authenticate", но не может.
Возможные решения, если вы можете изменить сервер:
- Добавьте поддельный заголовок "WWW-Authenticate", например:
WWW-Authenticate: Basic realm="fake"
. Это просто обходное решение, а не решение, но оно должно работать, и клиент http удовлетворен.
- Используйте код состояния HTTP
403
вместо 401
. Это семантика не то же самое и обычно при работе с логином 401 это правильный ответ (см. Здесь для подробного обсуждения), но его достаточно близко.
Возможные решения, если вы не можете изменить сервер:
Как писал @ErikZ в своем сообщении , вы можете использовать try & catch
HttpURLConnection connection = ...;
try {
// Will throw IOException if server responds with 401.
connection.getResponseCode();
} catch (IOException e) {
// Will return 401, because now connection has the correct internal state.
int responsecode = connection.getResponseCode();
}
Я также разместил это здесь: java.io.IOException: не найдено проблем с проверкой подлинности
Ответ 2
В самом деле, я решил эту проблему, включив заголовок WWW-Authenticate
в ответ сервера.
Однако, если вы добавите заголовок WWW-Authenticate: Basic realm=""
, и ваш API также будет использоваться веб-клиентами, некоторые веб-браузеры вызовут всплывающее окно с запросом на основные учетные данные.
Для меня правильное решение использует пользовательскую схему. Как объяснено в этом сообщении в блоге, я использую xBasic
вместо Basic
в ответе заголовка.
WWW-Authenticate: xBasic realm=""
С этим заголовком не только Volley корректно анализирует ответ, но также избегаю веб-браузеров, показывающих, что аутентификация всплывает.
Ответ 3
Я смог поймать эту клиентскую сторону при инициализации волейбола RequestQueue:
Volley.newRequestQueue(getApplicationContext(), new HurlStack() {
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) {
try {
return super.performRequest(request, additionalHeaders);
} catch (AuthFailureError authFailureError) {
authFailureError.printStackTrace();
// Log out / whatever you need to do here
} catch (IOException e) {
e.printStackTrace();
if (e.getMessage().equals("No authentication challenges found")) {
// This is the error. You probably will want to handle any IOException, not just those with the same message.
}
}
return null;
}
});
Ответ 4
Если сервер разбился, вы можете столкнуться с этой проблемой.
Шаги:
Ответ 5
Вы можете проверить, что e является экземпляром AuthFailureError.
Log.e(TAG, "AuthFailureError: " + (e instanceof AuthFailureError));