HttpURLConnection在Android 2.x中运行良好但在4.1中没有运行:没有发现身份验证挑战

时间:2012-08-04 17:09:03

标签: android authentication httpurlconnection

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

9 个答案:

答案 0 :(得分: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 =“...”。缺少引号可能是导致此问题的原因。如果确实如此,我们必须进一步调查,如果我们能够使它发挥作用。

答案 1 :(得分:25)

RFC2617

  

原始服务器使用401(未授权)响应消息      挑战用户代理的授权。这个回应必须      包括至少包含一个的WWW-Authenticate头字段      适用于所请求资源的挑战。

在Android中,当服务器返回java.io.IOException: No authentication challenges found401 Unauthorized状态代码而没有设置WWW-Authenticate标头时,HttpURLConnection getResponseCode()方法会抛出407 Proxy Authentication Required

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

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

答案 2 :(得分:6)

我有同样的问题。我发现这个解决方法,但它不适用于Android 2.在Jelly Bean上,它工作正常。只需使用getErrorStream()而不是getInputStream()。

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

答案 3 :(得分: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);

你得到了适当的回应。

答案 4 :(得分:0)

我遇到了类似的问题,需要使用Cookie才能正常运行。显然,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);

答案 5 :(得分:0)

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

以下是解决方案:

HTTP Basic Authentication issue on Android Jelly Bean 4.1 using HttpURLConnection

答案 6 :(得分:0)

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

答案 7 :(得分:0)

有一个解决方案

在您的代码中删除此

HttpConnection.setDoOutput(true);

它适用于ICSJelly Bean

答案 8 :(得分:0)

我使用的解决方案(我使用Android' Volley库)是用的 Square's OkHttp library。它们的实现正确处理了这个问题,并将按预期返回401。