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

时间:2014-03-10 03:11:05

标签: java android rest httpurlconnection digest-authentication

我正在开发一个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

2 个答案:

答案 0 :(得分:1)

如果资源受“摘要”保护,那么在您的代码中发送“基本”授权方案将无效,因为服务器无法识别它。

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

第三,“Authenticator.setDefault”很可能不会被请求,因为MicroSoft实施HTTP摘要认证会导致一些重要的来回(YMMV可能因我对此的回忆而有所不同)。因此,Sun / Oracle决定按照this document默认禁用此行为。

尽管如此,您可能最好还是考虑使用与Android捆绑在一起的Apache HTTP客户端来实现这一目标。包含了捆绑的实现摘要式身份验证。有一个位于here的“抢占式”摘要式身份验证示例。

需要注意的几点需要注意:

  • 关注存储在“target”中的“HttpHost” - 这个必须完全匹配要检索的URL中使用的主机名,协议端口和协议方案。
  • 提供的示例适用于HTTP Client 4.2.x.我不是100%确定Android中包含的版本,但您应该能够找到工作示例。

更新提交者提供了有关Google建议将HttpURLConnection与文章herehere一起使用的声明的其他评论。

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

没有迹象表明Android中的实现提供的摘要式身份验证的支持级别。正如我之前提到的,HttpURLConnection不会立即支持,因为它已知是错误的。

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

  • http.auth.digest.validateServer = “真”
  • http.auth.digest.validateProxy = “真”

通过这样做,这应该启用摘要认证方案。

我再次重申,与Android捆绑的Apache HTTP Client是专为解决基本Java HttpURLConnection的缺点而开发和设计的,为处理HTTP提供了更广泛,更强大的客户端( s)基于数据流。

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

我希望这一澄清可以帮助您实现目标。

答案 1 :(得分:0)

变化     ' Base64.encode ...' 至     ' Base64.encodeToString ...'