30

我有一些典型的代码,它们使用 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

9 回答 9

27

我目前面临同样的问题。在 4.1 Jelly Bean 上,我在 HttpURLConnection 上调用 getResponseCode() 时收到 IOException“未找到身份验证挑战”。

我在网上搜索了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。如果响应代码是 401 或 407,它会使用 HeaderParser.parseChallenges(..) 解析在响应中找到的质询标头。如果返回的 List 为空,则抛出异常。

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

我们目前正在调查究竟是什么导致该 List 为空,但怀疑我们的服务器可能在质询标头中使用 realm=... 而不是 realm="..." 。缺少引号可能是导致此问题的原因。我们必须进一步调查是否确实如此,如果我们可以让它发挥作用。

于 2012-09-28T16:15:46.343 回答
26

根据RFC2617

源服务器使用 401(未授权)响应消息来挑战用户代理的授权。该响应必须包含一个 WWW-Authenticate 头域,该域包含至少一个适用于所请求资源的质询。

在 Android 中,当服务器返回没​​有 WWW-Authenticate 标头集的a或状态码时, HttpURLConnection getResponseCode()方法会抛出。java.io.IOException: No authentication challenges found401 Unauthorized407 Proxy Authentication Required

如果您拥有服务器端 API,则可以通过在返回 401 或 407 时添加所需的 WWW-Authenticate 标头来修复它。在我的例子中,我在 PHP 中修复它如下:

header('WWW-Authenticate: OAuth realm="users"');
header('HTTP/1.1 401 Unauthorized');
于 2013-02-26T01:24:40.320 回答
6

我也有同样的问题。我找到了这个解决方法,但它不适用于 Android 2。在 Jelly Bean 上,它运行良好。只需使用 getErrorStream() 而不是 getInputStream()。

try
{
    responseStream = new BufferedInputStream(connection.getInputStream());
}
catch(IOException e)
{
    responseStream = new BufferedInputStream(connection.getErrorStream());
}
于 2012-11-29T11:21:58.857 回答
1

标题

我已经解决了果冻豆的问题。请在上述情况下使用以下代码

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

你得到了你需要的正确回应。

于 2013-02-14T06:34:28.390 回答
0

我在需要 cookie 才能正确运行的 Web 服务中遇到了类似的问题。显然,果冻豆默认情况下不会自动创建 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);
于 2013-01-04T22:21:55.833 回答
0

当使用基本身份验证而不调用 setDoOutput(true) 时,我们仍然遇到这个问题:

这是解决方案:

使用 HttpURLConnection 的 Android Jelly Bean 4.1 上的 HTTP 基本身份验证问题

于 2013-01-27T20:00:02.403 回答
0

检查您的服务器是否返回Error 401 - Not Authorised. 我相信 Android 代码会看到该响应,并认为它旨在提供身份验证详细信息。就我而言,我只是向我的服务器提供了错误的令牌。

于 2013-05-07T10:55:20.200 回答
0

有一个解决方案

在您的代码中删除此

HttpConnection.setDoOutput(true);

它将起作用ICSJelly Bean

于 2013-07-16T07:51:27.180 回答
0

我为此使用的一个解决方案(我正在使用 Android 的 Volley 库)是使用 Square 的 OkHttp 库。他们的实现正确地处理了这个问题,并将按预期返回 401。

于 2013-08-16T22:59:02.873 回答