Https比http有着更高的安全性.传送加密信息.有单向认证和双向认证.其中如果信任所有证书的话 那么无需将证书放入android asset文件夹下.如果不是,则需放入其文件夹中.httpclinet需要的是SSLSocketFactory 而httpurlconnect和okhttp则需要SSLContext.
一.HttpClient
1.信任所有证书(不建议)
public static SSLSocketFactory getSslSocketFactoryAll(Context context) {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryAll(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //允许所有主机
return sf;
} catch (Exception e) {
return null;
}
}
/**
* 自定义类 信任所有证书
* **/
public static class SSLSocketFactoryAll extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryAll(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,String authType)throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@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();
}
}
2.信任指定的证书
public static SSLSocketFactory getSslSocketFactory(Context context) {
try {
// 服务器端需要验证的客户端证书(双向认证时需要)
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// 客户端信任的服务器端证书
KeyStore trustStore = KeyStore.getInstance("PKCS12", "BC");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in = context.getResources().getAssets().open("12.crt");//加载服务端证书
//InputStream ksIn = context.getResources().getAssets() .open(KEY_STORE_CLIENT_PATH);//加载客户端给服务端自己的证书(双向)
Certificate ca = cf.generateCertificate(in);
//keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());//加载客户端证书(双向认证时候)
trustStore.load(null, null);
trustStore.setCertificateEntry("trust", ca);
return new SSLSocketFactory(trustStore);
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
按照需求 将上面返回的SSLSocketFactory加载到httpclient中,实现https连接
public static HttpClient getSslSocketFactoryHttp(Context context, int port) {
HttpClient httpsClient = new DefaultHttpClient();
SSLSocketFactory sslSocketFactory = getSslSocketFactory(context);
//SSLSocketFactory sslSocketFactory=getSslSocketFactoryAll(context);
// 设置http https支持
if (sslSocketFactory != null) {
Scheme sch = new Scheme("https", sslSocketFactory, port);//端口默认443
httpsClient.getConnectionManager().getSchemeRegistry()
.register(sch);
httpsClient.getConnectionManager().getSchemeRegistry()
.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
}
return httpsClient;
}
二.HttpUrlConnect,OkHttp实现方式
1.信任所有证书(不推荐)
public static SSLContext getAllSslContext() {
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
//信任所有证书写法(不推荐)
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
} }, new SecureRandom());
return sslContext;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
2.信任特定证书
private static SSLContext getSSLContext(Context context) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in = context.getResources().getAssets().open("12.crt");
Certificate ca = cf.generateCertificate(in);
// 服务器端需要验证的客户端证书
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
// 客户端信任的服务器端证书
KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
//读取客户端证书(asset文件夹)
// InputStream ksIn = context.getResources().getAssets()
// .open(KEY_STORE_CLIENT_PATH);
// context.getResources()//----------其他路径
// .openRawResource(R.drawable.kclient),CLIENT_KET_PASSWORD.toCharArray());
//读取服务端证书(asset文件夹)
InputStream tsIn = context.getResources().getAssets()
.open(KEY_STORE_TRUST_PATH);
try {
//加载客户端载证书和私钥
// keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
//加载服务端端载证书和私钥
//trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", ca);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// ksIn.close();
} catch (Exception ignore) {
}
try {
tsIn.close();
} catch (Exception ignore) {
}
}
SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);//取得SSL的SSLContext实例
//取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//初始化密钥管理器
trustManagerFactory.init(trustStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("X509");
keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
// sslContext.init(keyManagerFactory.getKeyManagers(),
// trustManagerFactory.getTrustManagers(), null);
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext;
} catch (Exception e) {
Log.e("tag", e.getMessage(), e);
}
return null;
}
通过上面不同的方式 将返回的SSLContext加入到HttpUrlConnect,OkHttp
1.HttpUrlConnect
/**
* 获取HttpsURLConnection
*
* @param context 上下文
* @param url 连接url
* @param method 请求方式
* @return HttpsURLConnection
*/
public static HttpsURLConnection getHttpsURLConnection(Context context,
String url, String method) {
URL u;
HttpsURLConnection connection = null;
try {
SSLContext sslContext = getSSLContext(context);
// SSLContext sslContext=getAllSslContext();
if (sslContext != null) {
u = new URL(url);
connection = (HttpsURLConnection) u.openConnection();
connection.setRequestMethod(method);//"POST" "GET"
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type",
"binary/octet-stream");
connection.setSSLSocketFactory(sslContext.getSocketFactory());
connection.setConnectTimeout(30000);
}
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
2.OkHttp
/**
* 获取SSL认证需要的HttpClient
*
* @param context 上下文
* @return OkHttpClient
*/
public static OkHttpClient getSSLContextHttp(Context context) {
OkHttpClient client = new OkHttpClient();
SSLContext sslContext = getSSLContext(context);
if (sslContext != null) {
client.setSslSocketFactory(sslContext.getSocketFactory());
}
return client;
}
至此就完成了android客户端对于Https访问的需求.