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

Posted

技术标签:

【中文标题】使用 HttpURLConnection 的 Android Jelly Bean 4.1 上的 HTTP 基本身份验证问题【英文标题】:HTTP Basic Authentication issue on Android Jelly Bean 4.1 using HttpURLConnection 【发布时间】:2013-01-11 02:07:56 【问题描述】:

我们正在使用 HTTP 基本身份验证向 Web 服务器发出基于 HttpURLConnection 的请求。 代码在 android 版本 2.x、3.x.、4.0.x 上运行良好 现在使用 Jelly Bean 和 v4.1.x 身份验证失败,LogCat 中显示以下消息:

01-27 10:54:18.886: ...::doReadRawData(731): An exception occured while reading data from remote host. httpURLConn.responseCode = 401 / httpURLConn.responseMessage = UNAUTHORIZED
01-27 10:54:18.886: ...::doReadRawData(731): java.io.IOException: No authentication challenges found

我们在 Android 文档中用于 HttpURLConnection 的身份验证代码:

private void doAuthorize() 
        Authenticator.setDefault(new Authenticator() 
            protected PasswordAuthentication getPasswordAuthentication() 
                return new PasswordAuthentication(USER, PASSWORD.toCharArray());
            
        );
    

经过进一步调查和故障排除,我们发现在 4.1 Jelly Bean 中没有调用此代码!

Android Jelly Bean 4.1 中基本身份验证的解决方法或正确方法是什么?

有人在这个相关主题的 Android 源代码中发现了不同,我认为我们遇到的问题与这种不同有关:HttpURLConnection worked fine in Android 2.x but NOT in 4.1: No authentication challenges found

【问题讨论】:

【参考方案1】:

我们能够通过以下新方法解决 Jelly Bean 不调用 Authenticator 的 getPasswordAuthentication() 的问题:

@TargetApi(Build.VERSION_CODES.FROYO) 
private void setJellyBeanAuth(HttpURLConnection httpConn) 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) 
        byte[] auth = (USER + ":" + PASSWORD).getBytes();
        String basic = Base64.encodeToString(auth, Base64.NO_WRAP);
        httpConn.setRequestProperty("Authorization", "Basic " + basic);
    

然后在打开连接后调用这个函数:

httpURLConn = (HttpURLConnection) url.openConnection();
setJellyBeanAuth(httpURLConn);

仅需要用于 Froyo 注释的 @TargetApi,因为我们仍然支持 API 7,而在 API 8 中添加了 Base64

【讨论】:

当我尝试做一个多部分时,这个标题技巧对我不起作用【参考方案2】:

对于 Android 的 httpURLConnection 的 401 UNAUTHORIZED 响应,您的服务器必须发回这样的身份验证标头... WWW-Authenticate: Bogus realm="blahblah", comment="使用表单登录" 根据https://www.rfc-editor.org/rfc/rfc2616 搜索“10.4.2 401 未授权”

【讨论】:

这是真正的解决方案。 Android HttpURLConnectionImpl 依赖服务端提供客户端进行身份验证的方式。

以上是关于使用 HttpURLConnection 的 Android Jelly Bean 4.1 上的 HTTP 基本身份验证问题的主要内容,如果未能解决你的问题,请参考以下文章

HttpURLConnection的使用步骤

android中的HttpUrlConnection的使用之二

使用HttpURLConnection进行请求各种接口

使用HttpURLConnection进行请求各种接口

如何使用 HttpURLConnection 在请求正文中发送数据?

有啥方法可以使用 HttpUrlConnection 正确获取上传进度