参考:http://blog.csdn.net/lmj623565791/article/details/48129405
HostnameVerifier-----此类是用于主机名验证的基接口。在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实 现程序来确定是否应该允许此连接。
X509TrustManager -------这个类用来验证是否是受信任的证书
HttpsURLConnection方式,不需要验证服务器证书的方式
https原理简述
Https协议是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的。
http与https
https与http相比速度上比http慢,但是比http协议安全,安全性主要体现在:
1加密传输数据,无法获取/修改数据
2验证数据的完整性,检测数据是否被篡改
3配备身份证书,防止冒充身份
https基本运行过程
传输数据之前会先进行一次握手:
传输数据之前客户端先发送加密通信请求,客户端需要向服务器端提供支持的协议版本(如TLS1.0),一个随机数,支持的加密算法,支持的压缩算法。服务器返回确定的加密通信协议版本,服务器生成的随机数确定使用的加密算法和服务器证书。
握手过程中如果出现任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。
代码实现htpps不需要验证服务器证书的过程中一般要实现两个类,
X509TrustManager -------这个类用来验证是否是受信任的证书
由于android6.0之后移除了httpclient,着重说下httpurlconnect方式。
如果需要验证服务器证书的httpurlconnection方式:需要从asset中获得证书(提前放置到asset中,也可以是其他地方 》 初始化证书工场 》 加载证书到秘钥库》加载秘钥到信任管理器》将之前的设置好的秘钥管理器,信任管理器等关联到SSLContext。
如果不需要验证服务器证书的httpurlconnection方式:初始化SSLContext》构建空的HostnameVerifier(主机身份验证类)类》构建空的X509TrustManager (证书信任验证类)类》将之前创建的主机身份验证类和证书信任验证类的对象关联(配置)SSLContext。
下面截取了4种情况的核心代码,上传项目到csdn了
项目地址:http://download.csdn.net/detail/zsdzsd20102010/9637175
=======================================================================
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new MyTrustManager() },
new SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection
.setDefaultHostnameVerifier(new MyHostnameVerifier());
HttpsURLConnection conn = (HttpsURLConnection) new URL(https)
.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
------------------------------------------------------------------------------------------------------------------------
private class MyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
// TODO Auto-generated method stub
return true;
}
}
------------------------------------------------------------------------------------------------------------------------------
private class MyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
}
==================================================================
HttpsURLConnection方式,需要验证服务器证书的方式
SSLContext sc = SSLContext.getInstance("TLS");
// 从assets中加载证书
InputStream inStream = getApplicationContext().getAssets().open(
"server.cer");
// 证书工厂
CertificateFactory cerFactory = CertificateFactory
.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(inStream);
// 密钥库
KeyStore kStore = KeyStore.getInstance("PKCS12");
kStore.load(null, null);
kStore.setCertificateEntry("trust", cer);// 加载证书到密钥库中
// 密钥管理器
KeyManagerFactory keyFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(kStore, null);// 加载密钥库到管理器
// 信任管理器
TrustManagerFactory tFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tFactory.init(kStore);// 加载密钥库到信任管理器
// 初始化
sc.init(keyFactory.getKeyManagers(), tFactory.getTrustManagers(),
new SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection conn = (HttpsURLConnection) new URL(https)
.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
==================================================================
HttpClient方式,不需要验证服务器证书的方式
public class SSLSocketFactoryEx extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryEx(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
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();
}
}
----------------------------------------------------------------------------------------------------------------------------
private synchronized HttpClient getHttpClient() {
// 创建 HttpParams 以用来设置HTTP参数(不是必须的)
BasicHttpParams tempHttpParams = new BasicHttpParams();
// 设置连接超时 SOCKET 超时已经缓存大小
HttpConnectionParams.setConnectionTimeout(tempHttpParams, 1000);
HttpConnectionParams.setSoTimeout(tempHttpParams, 1000 * 3);
// HttpConnectionParams.setSocketBufferSize(tempHttpParams,
// SOCKET_SIZE);
// 设置重定向,缺省值为true
HttpClientParams.setRedirecting(tempHttpParams, true);
// use expect-continue handshake
HttpProtocolParams.setUseExpectContinue(tempHttpParams, true);
// disable stale check
HttpConnectionParams.setStaleCheckingEnabled(tempHttpParams, false);
HttpProtocolParams.setVersion(tempHttpParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(tempHttpParams, HTTP.UTF_8);
HttpConnectionParams.setTcpNoDelay(tempHttpParams, true);
KeyStore trustStore;
ClientConnectionManager ccm = null;
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ccm = new ThreadSafeClientConnManager(tempHttpParams, registry);
} catch (Exception e) {
e.printStackTrace();
}
return new DefaultHttpClient(ccm, tempHttpParams);
}
==================================================================
httpClient方式,需要验证服务器证书的方式
private synchronized HttpClient getHttpClient() {
// 创建 HttpParams 以用来设置HTTP参数(不是必须的)
BasicHttpParams tempHttpParams = new BasicHttpParams();
// 设置连接超时 SOCKET 超时已经缓存大小
HttpConnectionParams.setConnectionTimeout(tempHttpParams, 1000);
HttpConnectionParams.setSoTimeout(tempHttpParams, 1000 * 3);
// HttpConnectionParams.setSocketBufferSize(tempHttpParams,
// SOCKET_SIZE);
// 设置重定向,缺省值为true
HttpClientParams.setRedirecting(tempHttpParams, true);
// use expect-continue handshake
HttpProtocolParams.setUseExpectContinue(tempHttpParams, true);
// disable stale check
HttpConnectionParams.setStaleCheckingEnabled(tempHttpParams, false);
HttpProtocolParams.setVersion(tempHttpParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(tempHttpParams, HTTP.UTF_8);
HttpConnectionParams.setTcpNoDelay(tempHttpParams, true);
ClientConnectionManager ccm = null;
try {
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ccm = new ThreadSafeClientConnManager(tempHttpParams, registry);
} catch (Exception e) {
e.printStackTrace();
}
return new DefaultHttpClient(ccm, tempHttpParams);
}
--------------------------------------------------------------------------------------------------------------------
static public void initKeyStore(Context context) {
AssetManager am = context.getAssets();
KeyStore keyStore = null;
InputStream ins = null;
try {
ins = am.open("server.cer");
// 读取证书
CertificateFactory cerFactory = CertificateFactory
.getInstance("X.509"); // 问1
Certificate cer = cerFactory.generateCertificate(ins);
// 创建一个证书库,并将证书导入证书库
keyStore = KeyStore.getInstance("PKCS12", "BC"); // 问2
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);
} catch (Exception e) {
} finally {
if (ins != null) {
try {
ins.close();
} catch (Exception e) {
}
}
}
if (keyStore != null) {
trustStore = keyStore;
}
}
==========================================================