参考链接
android httpClient(https/http)的优化构建方式一
android httpClient(https/http)的优化构建方式二
Java https请求 HttpsURLConnection
android 让webview支持https 双向认证(SSL)(一)
android 让webview支持https 双向认证(SSL)(二)
Https访问的相关知识中,主要分为单项验证和双向验证,双向验证在单项验证的基础上构建而成
关于单项验证,如果要细分的话,分为证书验证和普通验证(忽略验证),因为这项验证针对客户端,所以客户端有能力控制是否需要验证
忽略验证的方式
主要如下继承X509TrustManager和HostnameVerifier
public class SSLTrustManager implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager ,HostnameVerifier{
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
@Override
public boolean verify(String urlHostName, SSLSession session) { //允许所有主机
return true;
}
//封装
public static HttpURLConnection connect(String strUrl) throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new SSLTrustManager();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((HostnameVerifier) tm);
URL url = new URL(strUrl);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
return urlConn;
}
}
双向证书验证方式
如下,这里采用双向验证
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
public class HttpsPost {
/**
* 获得KeyStore.
* @param keyStorePath
* 密钥库路径
* @param password
* 密码
* @return 密钥库
* @throws Exception
*/
public static KeyStore getKeyStore(String password, String keyStorePath)
throws Exception {
// 实例化密钥库
KeyStore ks = KeyStore.getInstance("JKS");
// 获得密钥库文件流
FileInputStream is = new FileInputStream(keyStorePath);
// 加载密钥库
ks.load(is, password.toCharArray());
// 关闭密钥库文件流
is.close();
return ks;
}
/**
* 获得SSLSocketFactory.
* @param password
* 密码
* @param keyStorePath
* 密钥库路径
* @param trustStorePath
* 信任库路径
* @return SSLSocketFactory
* @throws Exception
*/
public static SSLContext getSSLContext(String password,
String keyStorePath, String trustStorePath) throws Exception {
// 实例化密钥库
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// 获得密钥库
KeyStore keyStore = getKeyStore(password, keyStorePath);
// 初始化密钥工厂
keyManagerFactory.init(keyStore, password.toCharArray());
// 实例化信任库
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// 获得信任库
KeyStore trustStore = getKeyStore(password, trustStorePath);
// 初始化信任库
trustManagerFactory.init(trustStore);
// 实例化SSL上下文
SSLContext ctx = SSLContext.getInstance("TLS");
// 初始化SSL上下文
ctx.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(), null);
// 获得SSLSocketFactory
return ctx;
}
/**
* 初始化HttpsURLConnection.
* @param password
* 密码
* @param keyStorePath
* 密钥库路径
* @param trustStorePath
* 信任库路径
* @throws Exception
*/
public static void initHttpsURLConnection(String password,
String keyStorePath, String trustStorePath) throws Exception {
// 声明SSL上下文
SSLContext sslContext = null;
// 实例化主机名验证接口
HostnameVerifier hnv = new MyHostnameVerifier();
try {
sslContext = getSSLContext(password, keyStorePath, trustStorePath);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
if (sslContext != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
}
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
}
/**
* 发送请求.
* @param httpsUrl
* 请求的地址
* @param xmlStr
* 请求的数据
*/
public static void post(String httpsUrl, String xmlStr) {
HttpsURLConnection urlCon = null;
try {
urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();
urlCon.setDoInput(true);
urlCon.setDoOutput(true);
urlCon.setRequestMethod("POST");
urlCon.setRequestProperty("Content-Length",
String.valueOf(xmlStr.getBytes().length));
urlCon.setUseCaches(false);
//设置为gbk可以解决服务器接收时读取的数据中文乱码问题
urlCon.getOutputStream().write(xmlStr.getBytes("gbk"));
urlCon.getOutputStream().flush();
urlCon.getOutputStream().close();
BufferedReader in = new BufferedReader(new InputStreamReader(
urlCon.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 测试方法.
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 密码
String password = "123456";
// 密钥库
String keyStorePath = "tomcat.keystore";
// 信任库
String trustStorePath = "tomcat.keystore";
// 本地起的https服务
String httpsUrl = "https://localhost:8443/service/httpsPost";
// 传输文本
String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><fruitShop><fruits><fruit><kind>萝卜</kind></fruit><fruit><kind>菠萝</kind></fruit></fruits></fruitShop>";
HttpsPost.initHttpsURLConnection(password, keyStorePath, trustStorePath);
// 发起请求
HttpsPost.post(httpsUrl, xmlStr);
}
}
单向证书验证
public static KeyStore getHttpsKeyStore()
{
InputStream ins = null;
try {
ins = new FileInputStream("srca.cer");
//读取证书
CertificateFactory cerFactory = CertificateFactory.getInstance("X.509"); //问1
Certificate cer = cerFactory.generateCertificate(ins);
//创建一个证书库,并将证书导入证书库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); //问2
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);
return keyStore;
} catch (Exception e) {
e.printStackTrace();
} finally {
if(ins!=null)
{
try {
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public void initSSLContext()
{
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(getHttpsKeyStore());
sslContext.init( null, trustManagerFactory.getTrustManagers(), new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession sslsession) {
if("localhost".equals(hostname)){
return true;
} else {
return false;
}
}
});
}