我正在尝试使用一些遗留代码,并在使用凌空时遇到问题。
我试图找到我们的主站点有api,它适用于一个帐户,但不适用于另一个帐户。我正在尝试弄清楚请求URL /标题中的差异以及响应中的内容,但我似乎无法在排序代码中找到将其打印到日志中的方法。
我得到的错误是
com.android.volley.NoConnectionError: java.io.IOException: No authentication challenges found
我已经读到这可能是由于401响应,但我真的不知道这意味着什么,或者至少如何证明/测试它。我真的很困惑,它适用于一个帐户而不是另一个帐户。
网址略有不同,一个是我们的英国网站,另一个是我们的AM,但除此之外没有区别。
谢谢
实际上,我通过包括这个来解决这个问题 WWW-Authenticate
服务器响应中的标头。
但是,如果添加标题 WWW-Authenticate: Basic realm=""
并且您的API也被Web客户端使用,一些Web浏览器将触发弹出请求基本凭据。
对我来说,正确的解决方案一直在使用自定义方案。正如本文所述 博客文章, 我用 xBasic
代替 Basic
在标题响应中。
WWW-Authenticate: xBasic realm=""
使用此标头,不仅Volley正确解析响应,而且还避免显示身份验证弹出的Web浏览器。
发生此错误的原因是服务器发送401(未授权)但未提供“WWW-Authenticate”,这是客户端下一步操作的提示。 “WWW-Authenticate”标题告诉客户端需要哪种认证(或者 基本 要么 消化)。这在无头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:未找到身份验证质询
初始化凌空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;
}
});
您可以检查e是AutofFailureError的实例。
Log.e(TAG, "AuthFailureError: " + (e instanceof AuthFailureError));