接着上一篇,这次讲解HttpURLConnection请求https处理方式,过程其实差不多,具体的有一点区别。
1、单向验证证书的https请求
首先获取SSLContext的对象,这是为了获取SSLSocketFactory的对象。
/**
* 获取Https的证书
* @param context Activity(fragment)的上下文
* @return SSL的上下文对象
*/
private static SSLContext getSSLContext(Context context) {
SSLContext s_sSLContext = null;
if (null != s_sSLContext) {
return s_sSLContext;
}
CertificateFactory certificateFactory = null;
InputStream inputStream = null;
KeyStore keystore = null;
String tmfAlgorithm = null;
TrustManagerFactory trustManagerFactory = null;
try {
certificateFactory = CertificateFactory.getInstance("X.509");
inputStream = context.getAssets().open("user.crt");//这里导入SSL证书文件
// inputStream = context.getAssets().open("51p2b_server_bs.pem");//这里导入SSL证书文件
Certificate ca = certificateFactory.generateCertificate(inputStream);
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("ca", ca);
tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
trustManagerFactory.init(keystore);
// Create an SSLContext that uses our TrustManager
s_sSLContext = SSLContext.getInstance("TLS");
s_sSLContext.init(null, trustManagerFactory.getTrustManagers(), null);
return s_sSLContext;
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String httpGet(String httpUrl) {
BufferedReader input = null;
StringBuilder sb = null;
URL url = null;
HttpURLConnection con = null;
try {
url = new URL(httpUrl);
try {
SSLContext sslContext = getSSLContext(activity);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection https= (HttpsURLConnection) url.openConnection();
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession sslsession) {
if("host".equals(hostname)){//判断域名是否和证书域名相等
return true;
} else {
return false;
}
}});
if (url.getProtocol().toLowerCase().equals("https")) {//判断是http还是https
//https.setHostnameVerifier(DO_NOT_VERIFY);
con = https;
} else {
con = (HttpURLConnection)url.openConnection();
}
input = new BufferedReader(new InputStreamReader(con.getInputStream()));
sb = new StringBuilder();
String s;
while ((s = input.readLine()) != null) {
sb.append(s).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e1) {
e1.printStackTrace();
} finally {
// close buffered
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// disconnecting releases the resources held by a connection so they may be closed or reused
if (con != null) {
con.disconnect();
}
}
return sb == null ? null : sb.toString();
}
2、信任所有证书的处理方式
/**
* 信任所有服务器,无需验证证书
*/
private static void trustAllHosts() {
final String TAG = "trustAllHosts";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
public String httpGet(String httpUrl) {
BufferedReader input = null;
StringBuilder sb = null;
URL url = null;
HttpURLConnection con = null;
try {
url = new URL(httpUrl);
try {
// trust all hosts
trustAllHosts();
HttpsURLConnection https= (HttpsURLConnection) url.openConnection();
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession sslsession) {
if("host".equals(hostname)){
return true;
} else {
return false;
}
}});
if (url.getProtocol().toLowerCase().equals("https")) {
https.setHostnameVerifier(DO_NOT_VERIFY);
con = https;
} else {
con = (HttpURLConnection)url.openConnection();
}
input = new BufferedReader(new InputStreamReader(con.getInputStream()));
sb = new StringBuilder();
String s;
while ((s = input.readLine()) != null) {
sb.append(s).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e1) {
e1.printStackTrace();
} finally {
// close buffered
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// disconnecting releases the resources held by a connection so they may be closed or reused
if (con != null) {
con.disconnect();
}
}
return sb == null ? null : sb.toString();
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
这样就不必验证证书了。
3、双向验证证书的操作
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 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);
}
}
4、如果你用的xutils3的框架, params.setSslSocketFactory(sslContext.getSocketFactory());这个方法认证证书