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

标签 java android rest httpurlconnection digest-authentication

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

但是,当我尝试通过下面的代码访问资源时,我收到 401 错误,并出现 java.io.FileNotFoundException。我对此进行了彻底研究,但没有成功,解决方案表示赞赏。

注意:我的 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());                                    
        }
    }
   );

我引用过这篇文章,但没有成功。 Connecting to remote URL which requires authentication using Java

最佳答案

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

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

第三,“Authenticator.setDefault”很可能不会被请求,因为 Microsoft 的 HTTP 摘要身份验证实现导致了一些重大的来回(YMMV 可能与我的内存不同)。因此,Sun/Oracle 决定按照 this document 默认禁用此行为。 .

也就是说,您最好考虑利用与 Android bundle 的 Apache HTTP 客户端来执行此操作。包含一个 bundle 实现摘要式身份验证。有一个“抢占式”摘要身份验证的示例,位于 here

需要注意的一些警告:

  • 密切注意“target”中存储的“HttpHost” - 它必须完全匹配正在检索的 URL 中使用的主机名、协议(protocol)端口和协议(protocol)方案。
  • 提供的示例适用于 HTTP 客户端 4.2.x。我不能 100% 确定 Android 中包含的版本,但您应该能够找到工作示例。

更新 提交者针对 Google 建议在文章 here 中使用 HttpURLConnection 的声明提供了附加评论。和 here .

虽然我相信 Tim Bray 关于为什么您应该使用提供的 HttpURLConnection 对象来执行这些调用的说法,但我不同意立即接受它们就面值而言。

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

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

  • http.auth.digest.validateServer="true"
  • http.auth.digest.validateProxy="true"

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

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

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

我希望此说明可以帮助您实现目标。

关于java - Android 401 使用 HttpURLConnection 连接到 REST 服务时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22291441/

相关文章:

java - 数组比 ArrayLists 更有效?

android - 在 android 16+ API 上保存密码

android - 将 Drawable 对象放置在 Android fragment 中布局的 View 中

rest - http-only 站点来测试 REST 请求?

java - 枚举:创建具有不同值的相同 "type"的多个枚举?

java - Java 8 中对多维数组的方法引用

java - 无法从 Eclipse 上的 Java 连接到 mongod 实例

android - 显示当前歌曲名称

rest - 事件溯源 - 如何处理竞争条件和 http 传递?

C# .NET Web API 文件上传和下载的最佳实践是什么?