【问题标题】:android - volley error No authentication challenges foundandroid - volley error 未找到身份验证挑战
【发布时间】:2013-12-16 17:12:00
【问题描述】:

我正在尝试使用一些遗留代码,但在使用 volley 时遇到了问题。

我正在尝试获取我们主站点拥有的 api,它适用于一个帐户,但不适用于另一个帐户。我正在尝试找出请求 URL/标头中可能存在的差异以及响应中返回的内容,但我似乎无法在 volley 代码中找到将其打印到日志的方法。

我得到的错误是

com.android.volley.NoConnectionError: java.io.IOException: No authentication challenges found

我已经阅读过这可能是由于 401 响应,但我真的不知道这意味着什么,或者至少不知道如何证明/测试它。我真的很困惑它适用于一个帐户而不是另一个帐户。

网址略有不同,一个用于我们的英国网站,另一个用于我们的 AM,但除此之外没有区别。

谢谢

【问题讨论】:

  • 这是一个错误,表示执行 Volley 请求时无法建立连接。
  • @Raghunandan 你知道是否还有比这更多的信息吗?任何响应细节等?
  • 无法建立连接。如果没有连接,哪里有机会得到响应
  • @bbalazs 我不认为这有帮助,我已经读过了。我认为这与截击无关。
  • @Raghunandan 是什么让您认为无法建立连接?我以为是身份验证不匹配时

标签: android authentication android-volley


【解决方案1】:

确实,我通过在服务器响应中包含WWW-Authenticate 标头解决了这个问题。

但是,如果您添加标头 WWW-Authenticate: Basic realm="" 并且您的 API 也被 Web 客户端使用,则某些 Web 浏览器会触发一个弹出窗口,要求您提供基本凭据。

对我来说,正确的解决方案是使用自定义方案。正如blog post 中所述,我在标头响应中使用xBasic 而不是Basic

WWW-Authenticate: xBasic realm=""

有了这个标头,Volley 不仅可以正确解析响应,而且我还可以避免 Web 浏览器显示身份验证弹出窗口。

【讨论】:

  • 很抱歉我很久以前问过这个问题,我什至不记得它与什么有关,而且那个遗留项目已经被关闭了。我会为您付出的努力投票赞成您的答案,但无法检查它是否正确,因此恐怕不会选择它作为答案。
  • @Russ 没问题!只是想帮助其他人寻找答案:)
  • 只是附注。您可以为方案使用任何字符串(例如,xBasic 如上所述),但还必须包含 realm=""(包括引号)以避免引发异常。
  • 如何在服务器响应中添加 WWW-Authenticate 标头
【解决方案2】:

发生此错误是因为服务器发送了 401(未经授权)但没有给出“WWW-Authenticate”提示客户端下一步该做什么。 “WWW-Authenticate”标头告诉客户端需要哪种身份验证(BasicDigest)。这在无头 http 客户端中通常不是很有用,但这就是标准的定义方式。发生错误是因为 lib 尝试解析“WWW-Authenticate”标头但不能。

如果您可以更改服务器,可能的解决方案:

  • 添加一个虚假的“WWW-Authenticate”标头,例如:WWW-Authenticate: Basic realm="fake"。这只是一种解决方法而不是解决方案,但它应该可以工作并且 http 客户端很满意。
  • 使用 HTTP 状态代码 403 而不是 401。它的语义不一样,通常在使用登录 401 时是正确的响应 (see here for a detailed discussion),但它足够接近。

如果您无法更改服务器,可能的解决方案:

正如@ErikZ 在他的post 中所写,您可以使用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 : No authentication challenges found

【讨论】:

  • 我正在尝试发送带有摘要式身份验证的标头,但不知道该怎么做(仍在寻找答案)。您有关于如何在 Android-Volley 中进行摘要(甚至是基本)身份验证的示例吗?
  • Basic 和 Digest 只是在 Basic 中放置一个类似于“授权:基本 QWxhZGRpbjpvcGVuIHNlc2FtZQ==”的标题,而在摘要中更复杂 - 这对 volley 来说并不特殊,您只需放置设置标题(google关于如何在截击中做到这一点)
  • 很抱歉我很久以前问过这个问题,我什至不记得它与什么有关,而且那个遗留项目已被关闭。我会为您付出的努力投票赞成您的答案,但无法检查它是否正确,因此恐怕不会选择它作为答案。
  • 很公平。我会留下它,因为我花了很长时间才理解这个问题 - 学习 REST/HTTP 规范有时并不像你想象的那么简单:)
  • 如何在服务器响应中添加 WWW-Authenticate 标头
【解决方案3】:

在初始化 volley 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】:

    如果服务器崩溃,您可能会遇到这个问题。 步骤:

    1. 停止 tomcat 服务器

    2. 转到运行 -> 服务 -> 重新启动您的数据库(例如:postgres)

    3. 启动 tomcat 服务器。

    【讨论】:

      【解决方案5】:

      您可以检查 e 是否为 AuthFailureError 实例。

      Log.e(TAG, "AuthFailureError: " + (e instanceof AuthFailureError));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        • 1970-01-01
        • 2015-11-08
        • 1970-01-01
        • 2013-09-05
        • 2012-10-14
        • 2013-07-05
        相关资源
        最近更新 更多