【问题标题】:Android: HTTPS Authentication Username and Password for HTTPClientAndroid:HTTPClient 的 HTTPS 身份验证用户名和密码
【发布时间】:2013-05-20 23:02:26
【问题描述】:

我正在通过 HTTPS 连接到服务器。我接受来自服务器的所有 x509 证书。现在我只需要将认证用户名和密码添加到httpclient。我使用的是 HTTPClient 而不是 DefaultHTTPClient。所有代码如下:

使用 HTTPClient 发送文件:

   protected void sendFile(String url, File file)
{
    try
    {
        HttpClient httpclient = new DefaultHttpClient();

        httpclient = sslClient(httpclient);

        CredentialsProvider credProvider = new BasicCredentialsProvider();
        credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
            new UsernamePasswordCredentials("YOUR USER NAME HERE", "YOUR PASSWORD HERE"));

        ((AbstractHttpClient) httpclient).setCredentialsProvider(credProvider);

        HttpPost httppost = new HttpPost(url);

        InputStreamEntity reqEntity = new InputStreamEntity(new FileInputStream(file), -1);
        reqEntity.setContentType("binary/octet-stream");
        reqEntity.setChunked(true); // Send in multiple parts if needed
        httppost.setEntity(reqEntity);

        HttpResponse response = httpclient.execute(httppost);
        int status = response.getStatusLine().getStatusCode();
        // Do something with response...
        Log.d(CLASSNAME, "Response: " + Integer.toString(status) + response.toString());

    }
    catch(Exception e)
    {
        Log.e(CLASSNAME, "Caught exception: " + e.getMessage());
        e.printStackTrace();
    }
}

private HttpClient sslClient(HttpClient client) {
    try {
        X509TrustManager tm = new X509TrustManager() { 
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new MySSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = client.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, client.getParams());
    } catch (Exception ex) {
        return null;
    }
}

这个类接受证书:

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.apache.http.conn.ssl.SSLSocketFactory;

public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(truststore);

    TrustManager tm = new X509TrustManager() {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    sslContext.init(null, new TrustManager[] { tm }, null);
}

public MySSLSocketFactory(SSLContext context) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
   super(null);
   sslContext = context;
}

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}
}

我得到以下异常:

org.apache.http.client.ClientProtocolException

有什么原因吗?

【问题讨论】:

  • 看我不知道你的情况,但我们在 Android 上遇到了 https 问题,唯一适用于所有版本的是 SSLSocket。由于某种原因,Apache 和 Java 客户端根本不想工作。它没有正确记录,并且有很多问题,祝你好运。

标签: android authentication httpclient


【解决方案1】:

我不确定你的问题到底是什么,但看看我不久前发布的this blog entry,它展示了如何在 Android 上执行 HTTPS,包括如何接受自签名服务器证书而不是盲目地接受接受所有证书。

编辑:要使用 HTTPUrlConnection 进行 BasicAuth(如博客文章示例中所用),您需要对连接执行以下操作:

String encoded = Base64.encode(username+":"+password); 
connection.setRequestProperty("Authorization", "Basic "+encoded);

另见Preemptive Basic Auth with HttpUrlConnection?

【讨论】:

  • 我相信它与 HttpClient httpclient = new DefaultHttpClient();因为它没有 setCredentialProvider 方法,所以我必须强制转换 HTTPClient。
  • 另外,你将如何添加身份验证
  • 您的实际答案不应该是博客文章的链接(现在已损坏),如果不能只是链接,您不妨发表评论。
猜你喜欢
  • 2017-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 2018-07-13
相关资源
最近更新 更多