Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android 401使用HttpURLConnection连接到REST服务时出错_Java_Android_Rest_Httpurlconnection_Digest Authentication - Fatal编程技术网

Java Android 401使用HttpURLConnection连接到REST服务时出错

Java Android 401使用HttpURLConnection连接到REST服务时出错,java,android,rest,httpurlconnection,digest-authentication,Java,Android,Rest,Httpurlconnection,Digest Authentication,我正在开发一个android应用程序,希望使用URLConnection连接到REST服务。使用摘要身份验证对资源进行保护。我可以通过浏览器成功访问REST服务。我不想使用HttpClient,因为URLConnection是未来更流行的连接方式 但是当我试图通过下面的代码访问资源时,我得到了一个带有java.io.FileNotFoundException的401错误。我对此进行了彻底的研究,但没有成功,对此我表示赞赏 注意:我的REST服务是使用Grails开发的,我在android仿真器中

我正在开发一个android应用程序,希望使用URLConnection连接到REST服务。使用摘要身份验证对资源进行保护。我可以通过浏览器成功访问REST服务。我不想使用HttpClient,因为URLConnection是未来更流行的连接方式

但是当我试图通过下面的代码访问资源时,我得到了一个带有java.io.FileNotFoundException的401错误。我对此进行了彻底的研究,但没有成功,对此我表示赞赏

注意:我的REST服务是使用Grails开发的,我在android仿真器中运行此代码,代码是在windows 64位操作系统上的Eclipse中开发的

代码

URL myurl = new URL("http://10.0.2.2:8080/MyREST/customers");

HttpURLConnection myurlConnection = (HttpURLConnection) myurl.openConnection();

String basicAuth =  "Basic " + (Base64.encode(userpass.getBytes(),android.util.Base64.DEFAULT)).toString();
myurlConnection.setRequestProperty ("Authorization", basicAuth);

try {
    int responseCode1 = ((HttpURLConnection) myurlConnection).getResponseCode();
    Log.i("MyLongOperation", "Check connection" +Integer.toString(responseCode1) );

    InputStream in = new BufferedInputStream(myurlConnection.getInputStream());
    readStream(in);
}
finally {
   myurlConnection.disconnect();
  }     
我还尝试在全局级别设置身份验证,但没有效果

Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password.toCharArray());                                    
        }
    }
   );

我提到了这篇文章,但没有成功

如果资源受“摘要”保护,则在代码中发送“基本”授权方案将不起作用,因为服务器无法识别它

其次,通过使用“抢占式”身份验证,将授权头设置为不请求它,这是一种安全漏洞。您将向服务器发送尚未请求的信息

第三,“Authenticator.setDefault”很可能不会被请求,因为微软实施HTTP摘要身份验证(根据我的记忆,YMMV可能会有所不同)会造成一些重大的来回。因此,Sun/Oracle决定按照默认设置禁用此行为

也就是说,您最好考虑使用与Android捆绑的Apache HTTP客户端来实现这一点。其中包括一个捆绑的实现摘要身份验证。这里有一个“抢占式”摘要身份验证的示例

需要注意的几个注意事项:

  • 请密切注意存储在“target”中的“HttpHost”-此必须与正在检索的URL中使用的主机名、协议端口和协议方案完全匹配
  • 提供的示例是针对HTTP客户端4.2.x的。我不是100%确定Android中包含的版本,但您应该能够找到工作示例
更新提交人就谷歌建议在文章和内容中使用HttpURLConnection的声明提供了补充意见

虽然我相信Tim Bray关于您为什么应该使用提供的HttpURLConnection对象来执行这些调用的推理所作的陈述,但我不同意他们应该立即从表面上接受

没有迹象表明Android中的实现对摘要认证的支持程度。正如我前面提到的,HttpURLConnection不支持立即连接,因为众所周知它有缺陷

如果您决定使用HTTP摘要身份验证,不管大多数社区认为它不稳定,我将尝试在Android生命周期中尽早在应用程序中设置以下系统属性:

  • http.auth.digest.validateServer=“true”
  • http.auth.digest.validateProxy=“true”
通过这样做,应该可以启用摘要身份验证方案

我再次重申,与Android捆绑的Apache HTTP客户端是专门为解决基本Java HttpURLConnection的不足而开发和设计的,它为处理基于HTTP的数据流提供了一个更广泛、更健壮的客户端

我建议您也尝试几件事,看看是否可以将容器配置为提供“基本”身份验证保护。另一个更复杂的选项可能是提供X.509基于证书的身份验证

我希望这一澄清能帮助你实现目标。

改变 “Base64.encode…” 到
“Base64.encodeToString…”

感谢您提供的信息,我确实在其他项目中使用了Apache Http客户端,以便成功地进行连接。我希望使用的是HttpURLConnection,因为这是Google建议今后使用的连接。话虽如此,看来我可能被Htttp客户端卡住了。你能澄清一下你在哪里看到谷歌在这方面的建议吗?ApacheHTTP客户端的目的是解决标准HTTPUrlConnection未提供的重大缺陷和功能。特别是这一特定的摘要身份验证案例,我记得几年前,虽然它将成为下一代身份验证机制,但在实现过程中却分崩离析。这是JVM中默认情况下不启用它的部分原因。或引用安卓文档-“我们建议针对姜饼和更高版本的应用程序使用HttpURLConnection”此时,我必须满足于AndroidHttpClient,感谢您为我指明了正确的方向。