我正在开发一个Android应用程序,并希望使用 URLConnection 连接到 REST 服务。使用摘要式身份验证保护资源。我可以通过浏览器成功访问REST服务。我不想要使用 HttpClient ,因为 URLConnection 是更新的未来连接方式。
但是当我尝试通过下面的代码访问资源时,我得到了一个带有java.io.FileNotFoundException 的 401错误。我已经彻底研究过但没有成功,解决方案很受欢迎。
注意:我的REST服务是使用Grails开发的,我在android模拟器中运行此代码,在Windows 64位操作系统上使用Eclipse开发代码。
CODE
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());
}
}
);
我已经提到了这篇文章 - 没有成功。 Connecting to remote URL which requires authentication using Java
答案 0 :(得分:1)
如果资源受“摘要”保护,那么在您的代码中发送“基本”授权方案将无效,因为服务器无法识别它。
其次,通过使用“抢占式”身份验证,设置授权标头没有被请求是一种安全漏洞。您将向服务器发送尚未请求的信息。
第三,“Authenticator.setDefault”很可能不会被请求,因为MicroSoft实施HTTP摘要认证会导致一些重要的来回(YMMV可能因我对此的回忆而有所不同)。因此,Sun / Oracle决定按照this document默认禁用此行为。
尽管如此,您可能最好还是考虑使用与Android捆绑在一起的Apache HTTP客户端来实现这一目标。包含了捆绑的实现摘要式身份验证。有一个位于here的“抢占式”摘要式身份验证示例。
需要注意的几点需要注意:
更新提交者提供了有关Google建议将HttpURLConnection与文章here和here一起使用的声明的其他评论。
虽然我相信Tim Bray关于为什么的推理的陈述,你应该使用提供的HttpURLConnection对象来执行这些调用,但我不同意他们应该立即被接受在面值。
没有迹象表明Android中的实现提供的摘要式身份验证的支持级别。正如我之前提到的,HttpURLConnection不会立即支持,因为它已知是错误的。
如果您决定使用HTTP摘要式身份验证,无论社区的大多数人认为它是不稳定的,我会尝试尽可能早地在您的应用程序中设置以下系统属性在Android生命周期中:
通过这样做,这应该启用摘要认证方案。
我再次重申,与Android捆绑的Apache HTTP Client是专为解决基本Java HttpURLConnection的缺点而开发和设计的,为处理HTTP提供了更广泛,更强大的客户端( s)基于数据流。
我建议您尝试一些事情,看看您是否可以配置容器以提供“基本”身份验证保护。另一个更复杂的选择是可能提供基于X.509证书的身份验证。
我希望这一澄清可以帮助您实现目标。
答案 1 :(得分:0)
变化 ' Base64.encode ...' 至 ' Base64.encodeToString ...'