HttpURLConnection在Android 2.x中工作正常,但在4.1中没有:没有发现身份validation的挑战

我有一些典型的代码使用HttpURLConnection获得一个URL的文件。 他们在Android 1.x和2.x中工作正常。 但在Android 4.1失败!

我在网上search,但发现一些类似的信息。 有人请帮忙调查这个问题吗?

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方法抛出一个exception:

 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.1 Jelly Bean上,当在HttpURLConnection上调用getResponseCode()时,会收到IOException“No authentication challenge found”。

我在网上search了解Android源代码中发生了什么变化,发现如下:4.0.4(working): 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中可以看到的,getAuthorizationCredentials()方法抛出IOExceptionexception。 它使用HeaderParser.parseChallenges(..)parsing在响应中find的挑战头,如果响应代码是401或者407。如果返回的List是空的,则引发Exception。

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

我们目前正在调查究竟是什么原因导致这个List为空,但是怀疑我们的服务器可能在challenge标题中使用realm = …而不是realm =“…”。 缺less引号可能是导致此问题的原因。 如果确实是这样的话,我们还得进一步调查,如果我们能够做到的话。

根据RFC2617 :

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

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

如果你拥有服务器端API,那么当你返回401或者407时,你可以通过添加所需的WWW-Authenticate头来解决这个问题。在我的情况下,我使用如下的方法修复了它:

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

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

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

标题

我已经解决了果冻豆的问题。 上面的场景请使用下面的代码

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

你根据需要得到了正确的答复。

我遇到了一个类似的问题,需要cookies才能正常运行。 显然果冻豆不会自动创build一个cookie存储默认(不像以前的版本),所以服务无法find我的会话,并扔了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); 

当使用基本身份validation而不是调用setDoOutput(true)时,我们仍然有这个问题:

这是解决scheme:

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

检查您的服务器是否正在返回Error 401 - Not Authorised 。 我相信Android代码看到了这个响应,并且相信这是为了提供authentication细节。 在我的情况下,我只是提供错误的令牌给我的服务器。

有一个解决scheme

在你的代码中删除这个

HttpConnection.setDoOutput(真);

它将在ICSJelly Bean

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