⑩SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。
下面我们就来写一下Https请求
String path = "https://www.baidu.com";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
InputStream is = conn.getInputStream();
String string = Utils.inputStream2String(is);
System.out.println(string);
这个可以正常访问,它就会将百度的html返回回来,那下面我们就url改成其他的看看,将其改成我tomcat下的一个工程网址(已放开了https配置,设置了自签名证书):https://localhost:8443/Test/myTest
String path = "https://localhost:8443/Test/myTest";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
InputStream is = conn.getInputStream();
String string = Utils.inputStream2String(is);
System.out.println(string);
这时就访问不了了,报了一个javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target错误
1.无条件的设置信任所有的证书,但是这样做是不安全的
public static void main(String[] args) {
try {
//初始化SSLContext
SSLContext context = SSLContext.getInstance("TLS");//TLS和SSL都可以
//设置信任管理器
TrustManager[] managers = new TrustManager[]{new EmptyTrustManager()};
context.init(null, managers, null);
//这个必须在HttpsURLConnection生成对象之前设置
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
String path = "https://localhost:8443/Test/myTest";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//这时设置SSLSocketFactory没有用
//conn.setDefaultSSLSocketFactory(conn.getSSLSocketFactory());
InputStream is = conn.getInputStream();
String string = Utils.inputStream2String(is);
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}
}
static class EmptyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
2.设置只信任与服务器设置的jks对应的cer证书。当你将自己的项目的网络请求改为https时,后台哥们会给你一个xxx.cer证书,这个证书就会和后台的xxx.jks进行验证校验。我们可以将xxx.cer放到工程中,去读取文件,也可以将其打印成字符串,将字符串放到代码中去读取。以下我是以字符串的形式使用的
static String chen = "-----BEGIN CERTIFICATE-----\n"+
"MIIDWTCCAkGgAwIBAgIENIaROTANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJDTjENMAsGA1UE"+
"CBMEY2hlbjENMAsGA1UEBxMEY2hlbjENMAsGA1UEChMEY2hlbjENMAsGA1UECxMEY2hlbjESMBAG"+
"A1UEAxMJbG9jYWxob3N0MB4XDTE3MDIxMzA5NDIzN1oXDTI2MTIyMzA5NDIzN1owXTELMAkGA1UE"+
"BhMCQ04xDTALBgNVBAgTBGNoZW4xDTALBgNVBAcTBGNoZW4xDTALBgNVBAoTBGNoZW4xDTALBgNV"+
"BAsTBGNoZW4xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC"+
"ggEBAKolNf440rZx58iz5P58VrWWPMQDZPMYuDDeZMENHRIUOu+PmjKwpmJUqVnKMvyGFj9VtoPE"+
"kZE7NQLzJ0FIfaTBLaHRTYLisk3qnVXgZyZq/rrLq935SURCRl76NP+pAyXBoWVUkvzRYwXfhFUi"+
"zO5yjH+ZFfQzjGWCugd8oYCLKmP+pJnlP/faNu7YDjL9JkOm6KiEnmkklkSJXrBBxmpsy0lSShwY"+
"rNoZ4wW8XwgbNdwjM+Z4+IeOD/gBZMSrI8n8TLKBFH6IydFJOkwhHO1BvdzNQHrcXF0CRqM5ctW4"+
"K7LXXE8OJg59b28ghdiqVAWRnSEyIYNgEBLkXnaU95UCAwEAAaMhMB8wHQYDVR0OBBYEFDt5QPgy"+
"T3yfkb9iXV92Wzo1YndfMA0GCSqGSIb3DQEBCwUAA4IBAQA9ZVQIGQERDvDlsjlSzmhcrX0Gpdxf"+
"kFmgXEc+Tck04l2VaT70YXYztcWTm8iPlxAOTAjxRE0syIbbAQ4UPba0hFINCPpvCD31ax3ukFUj"+
"NJH+rZUwo1HjV8qzKAA4nd3f31PRg3yyAzmgfAwqVNxiq26YVglvV6h3TnC6dgcnV4sejOvv5nTA"+
"7qc0cbQvGIEz4bEwIc+0l2/gwIoeUIquM6OAQTVzX9LuJ1aUTpenut+9G+vkEO3pfy4gdnOOXntW"+
"uzqhaUV9gxOd1et10n1pvDcYNG6hhAkvotgV8Pl+NnDZ22Hqin1XB1cOZv18zHxC9WThRma3VN0V"+
"z08eItRz\n"+
"-----END CERTIFICATE-----";
public static void main(String[] args) {
try {
ByteArrayInputStream baos = new ByteArrayInputStream(chen.getBytes());
SSLContext sslContext = getSSLContext(baos);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
String path = "https://localhost:8443/Test/myTest";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//conn.setDefaultSSLSocketFactory(conn.getSSLSocketFactory());
InputStream is = conn.getInputStream();
String string = Utils.inputStream2String(is);
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}
}
static SSLContext getSSLContext(InputStream is){
try{
//初始化SSLContext
SSLContext context = SSLContext.getInstance("TLS");//TLS和SSL都可以
// 1.导入证书
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(is);
// 2.证书导入密钥库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry("srca", certificate);
// 3.把密钥库放入信任管理器
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// 4.生成信任管理器
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
// 将信任管理器设置到SSLContext
context.init(null, trustManagers, null);
return context;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
如果url中的Hostname用的是IP则情况就不一样了,如果是String path = "https://127.0.0.1:8443/Test/myTest";再次访问的时候,会报javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present错误。
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
此设置应和SSLSocketFactory一样,在生成HttpsURLConnection之前设置,不然无效,所以main方法中代码应为
public static void main(String[] args) {
try {
ByteArrayInputStream baos = new ByteArrayInputStream(chen.getBytes());
SSLContext sslContext = getSSLContext(baos);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
String path = "https://127.0.0.1:8443/Test/myTest";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//conn.setDefaultSSLSocketFactory(conn.getSSLSocketFactory());
InputStream is = conn.getInputStream();
String string = Utils.inputStream2String(is);
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}
}
这时就可以正常访问了。
服务器端配置https
下面我们就来讲解如何生成自签名证书,和tomcat如何部署,完成这两步tomcat就可以使用https访问了,首先我们使用java自带的keytool工具生成证书,win+R打开运行,输入cmd打开cmd命令窗体,按照如下方式输入:
如何生成https证书:
1.生成jks,使用如下的命令就会生成一个chen.jks,密码为123456,jks是服务端tomcat配置https时使用的证书
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -genkey -alias chen -keyalg
RSA -keystore C:\CJ\chen.jks -validity 3600 -storepass 123456
您的名字与姓氏是什么?
[Unknown]: localhost
您的组织单位名称是什么?
[Unknown]: chen
您的组织名称是什么?
[Unknown]: chen
您所在的城市或区域名称是什么?
[Unknown]: chen
您所在的省/市/自治区名称是什么?
[Unknown]: chen
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=localhost, OU=chen, O=chen, L=chen, ST=chen, C=CN是否正确?
[否]: y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
2.生成cer,使用如下命令和chen.jks就会生成一个chen.cer,xxx.cer是客户端https访问时用于与服务端jks进行校验的
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -export -alias chen -file C
:\CJ\chen.cer -keystore C:\CJ\chen.jks -storepass 123456
存储在文件 中的证书
3.打印cer,使用如下命令就可以打印cer中的字符串,就是上述提到的将cer打印成字符串,放入代码中,就不需要将xxx.cer放到工程中了。
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -printcert -rfc -file C:\CJ\chen.cer
-----BEGIN CERTIFICATE-----
MIIDWTCCAkGgAwIBAgIENIaROTANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJDTjENMAsGA1UE
CBMEY2hlbjENMAsGA1UEBxMEY2hlbjENMAsGA1UEChMEY2hlbjENMAsGA1UECxMEY2hlbjESMBAG
A1UEAxMJbG9jYWxob3N0MB4XDTE3MDIxMzA5NDIzN1oXDTI2MTIyMzA5NDIzN1owXTELMAkGA1UE
BhMCQ04xDTALBgNVBAgTBGNoZW4xDTALBgNVBAcTBGNoZW4xDTALBgNVBAoTBGNoZW4xDTALBgNV
BAsTBGNoZW4xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKolNf440rZx58iz5P58VrWWPMQDZPMYuDDeZMENHRIUOu+PmjKwpmJUqVnKMvyGFj9VtoPE
kZE7NQLzJ0FIfaTBLaHRTYLisk3qnVXgZyZq/rrLq935SURCRl76NP+pAyXBoWVUkvzRYwXfhFUi
zO5yjH+ZFfQzjGWCugd8oYCLKmP+pJnlP/faNu7YDjL9JkOm6KiEnmkklkSJXrBBxmpsy0lSShwY
rNoZ4wW8XwgbNdwjM+Z4+IeOD/gBZMSrI8n8TLKBFH6IydFJOkwhHO1BvdzNQHrcXF0CRqM5ctW4
K7LXXE8OJg59b28ghdiqVAWRnSEyIYNgEBLkXnaU95UCAwEAAaMhMB8wHQYDVR0OBBYEFDt5QPgy
T3yfkb9iXV92Wzo1YndfMA0GCSqGSIb3DQEBCwUAA4IBAQA9ZVQIGQERDvDlsjlSzmhcrX0Gpdxf
kFmgXEc+Tck04l2VaT70YXYztcWTm8iPlxAOTAjxRE0syIbbAQ4UPba0hFINCPpvCD31ax3ukFUj
NJH+rZUwo1HjV8qzKAA4nd3f31PRg3yyAzmgfAwqVNxiq26YVglvV6h3TnC6dgcnV4sejOvv5nTA
7qc0cbQvGIEz4bEwIc+0l2/gwIoeUIquM6OAQTVzX9LuJ1aUTpenut+9G+vkEO3pfy4gdnOOXntW
uzqhaUV9gxOd1et10n1pvDcYNG6hhAkvotgV8Pl+NnDZ22Hqin1XB1cOZv18zHxC9WThRma3VN0V
z08eItRz
-----END CERTIFICATE-----
4.tomcat服务器配置 ,在tomcat下的conf文件夹下的server.xml中配置
在server.xml中的https默认配置的port为8443,你也可以修改,当你的电脑的8443端口被其他应用占用的时候,你就可以修改。这是重新启动tomcat时,这时你的服务器就可以使用https访问了。
双向证书验证
前面的https请求时,是服务器一个chen.jks,客户端一个chen.cer。那么双向证书验证,就还需要再次之前的配置上,再加上服务器一个chen_client.cer,客户端一个chen_client.jks。
重新生成一个证书
1.生成jks
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -genkey -alias chen -keyalg
RSA -keystore C:\CJ\chen.jks -validity 3600 -storepass 123456
您的名字与姓氏是什么?
[Unknown]: localhost
您的组织单位名称是什么?
[Unknown]: chen
您的组织名称是什么?
[Unknown]: chen
您所在的城市或区域名称是什么?
[Unknown]: chen
您所在的省/市/自治区名称是什么?
[Unknown]: chen
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=localhost, OU=chen, O=chen, L=chen, ST=chen, C=CN是否正确?
[否]: y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
2.生成cer
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -export -alias chen -file C
:\CJ\chen.cer -keystore C:\CJ\chen.jks -storepass 123456
存储在文件 中的证书
需要将cer证书添加到jks中,不然,如果服务端使用cer证书,会报一个Invalid keystore format错误
C:\Program Files\Java\jdk1.7.0_67\bin>keytool -import -alias chen_client -file C
:\CJ\chen_client.cer -keystore C:\CJ\chen_client_for_server.jks
3.修改tomcat的配置文件
需要将之前的clientAuth="false"改为clientAuth="true",在增加一个字段truststoreFile="C:\\CJ\\chen_client_for_server.jks",指明jks的路径。
当是双向证书验证验证时,如果在tomcat/conf/sever.xml文件中的配置属性clientAuth="false",没有将其改为true,这是的双向证书验证验依然是单向的,客户端不做任何修改,https依然可以访问,如果将其改为true,就访问不了了。
//初始化keystore
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream iStream = new FileInputStream("chen_client.jks");
clientKeyStore.load(iStream, "123456".toCharArray());
//将keystore放入密钥管理器
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
//生成密钥管理器
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
// 将信任管理器设置到SSLContext
context.init(keyManagers, trustManagers, null);
这时就可以进行网络请求了(java平台),客户端和服务器就是双向证书验证方式,网络请求就会更加的安全可靠。(如果是双向证书验证的tomcat,如果客户端不给kayManagers就会报 javax.net.ssl.SSLException: Connection closed by peer 错误)
URLConnection双向证书验证的https请求:
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.tydz.taoyuan.R;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class HttpsActivity extends AppCompatActivity {
static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText(msg.obj.toString());
}
};
static String chen = "-----BEGIN CERTIFICATE-----\n" +
"MIIDWTCCAkGgAwIBAgIEcWnCMTANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJDTjENMAsGA1UE\n" +
"CBMEY2hlbjENMAsGA1UEBxMEY2hlbjENMAsGA1UEChMEY2hlbjENMAsGA1UECxMEY2hlbjESMBAG\n" +
"A1UEAxMJbG9jYWxob3N0MB4XDTE3MDIxMzE0MTIzNVoXDTI2MTIyMzE0MTIzNVowXTELMAkGA1UE\n" +
"BhMCQ04xDTALBgNVBAgTBGNoZW4xDTALBgNVBAcTBGNoZW4xDTALBgNVBAoTBGNoZW4xDTALBgNV\n" +
"BAsTBGNoZW4xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAOCj9+qaE/DcDtJnEpeSc0+byTO3/yM673C4sgax7n4lCnjtmhgqiwASTCOnEMRJ6llmo/M8\n" +
"+msz9i+1vE4lte7AkZ/3Wfu04BXq9wmDlVNWU3kU6TfZMUhqifTvRC6zQmfJaBdS6SSfmBslrUUC\n" +
"ntD19vvGRLPkEt05s0itG54ex41fSgA4pBtj6qpBjLMS/03fCD6y3YdL+r0dN6bDxAuLo+2flJEy\n" +
"9CrnXEzLcZ172zD+5mfvhFI7F1fF1kdjT4pNi22sap5AOFZazaK7snq03cLTchC7yBwcPCJ6IqzY\n" +
"Yw6bVb79cj6nntbTb6lsrL7wv2kR8ubtiRTrrtCP2YMCAwEAAaMhMB8wHQYDVR0OBBYEFF5ZFY02\n" +
"FejgLSsO9DOZppwUhGS4MA0GCSqGSIb3DQEBCwUAA4IBAQCNg76X3tRCtnDi7cT5M8ADMzSUlYvA\n" +
"CaVYKQ+lB3WBLuqR3wVVJ/zeSGqiR4F59cj6Oij+fk5Fu05n+0nXX/sdirf2RTW1eaA+SzPYXdgA\n" +
"0u8XJdaPu58q0GCPFpUv24ljzQEr/hZBS9HWlHmkgByecpgrrToOc3jJNIQr8g1NVO/b8RCBFyx8\n" +
"Ax+Ytp8XNGKbmMnXifBxBnhMCT0DptmZuYsTacZ5qLqEhszChYSM3drYhoNId1HlLLeQbUumbB/8\n" +
"N1BVVH2LYPTJgKdXTQAzTWiUAss/HD78fe30qI3MDrZ1h4eF+vCHqOwAOiLxQ0Rpb5oMsVCblmoR\n" +
"+ool1ljG\n" +
"-----END CERTIFICATE-----";
private static TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_https);
mTextView = (TextView) findViewById(R.id.textview);
new Thread(){
@Override
public void run() {
super.run();
try {
net();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
private void net() throws Exception{
ByteArrayInputStream baos = new ByteArrayInputStream(chen.getBytes());
//InputStream iStream = new FileInputStream("chen_client.jks");
InputStream iStream = getAssets().open("chen_client.bks");
SSLContext sslContext = getSSLContext(baos,iStream);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
String path = "https://10.0.2.2:8444/OkHttp/text";
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//********************************
//POST请求
/*
conn.addRequestProperty("Content-Type", "application/json");
conn.addRequestProperty("Connection", "Keep-Alive");// 维持长连接
conn.addRequestProperty("Charset", "UTF-8");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
OutputStream outputStream = conn.getOutputStream();
outputStream.write("{\"name\":chen}".getBytes("UTF-8"));
outputStream.flush();
outputStream.close();
*/
//************************************
//conn.setDefaultSSLSocketFactory(conn.getSSLSocketFactory());
InputStream is = conn.getInputStream();
String string = inputStream2String(is);
System.out.println(string);
sendMsg(string);
}
private void sendMsg(String msg){
Message message = mHandler.obtainMessage();
message.obj = msg;
mHandler.sendMessage(message);
}
SSLContext getSSLContext(InputStream cer,InputStream bks){
try{
//初始化SSLContext
SSLContext context = SSLContext.getInstance("TLS");//TLS和SSL都可以
// 1.导入证书
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(cer);
// 2.证书导入密钥库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry("srca", certificate);
// 3.把密钥库放入信任管理器
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// 4.生成信任管理器
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
//初始化keystore
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientKeyStore.load(bks, "123456".toCharArray());
//将keystore放入密钥管理器
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
//生成密钥管理器
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
// 将信任管理器设置到SSLContext
context.init(keyManagers, trustManagers, null);
return context;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public static String inputStream2String(InputStream in) throws IOException {
int len = -1;
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((len = in.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
baos.close();
return baos.toString("UTF-8");
}
}
Volley双向证书验证的https请求:
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class MainActivity extends AppCompatActivity {
static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText(msg.obj.toString());
}
};
static String chen = "-----BEGIN CERTIFICATE-----\n" +
"MIIDWTCCAkGgAwIBAgIEcWnCMTANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJDTjENMAsGA1UE\n" +
"CBMEY2hlbjENMAsGA1UEBxMEY2hlbjENMAsGA1UEChMEY2hlbjENMAsGA1UECxMEY2hlbjESMBAG\n" +
"A1UEAxMJbG9jYWxob3N0MB4XDTE3MDIxMzE0MTIzNVoXDTI2MTIyMzE0MTIzNVowXTELMAkGA1UE\n" +
"BhMCQ04xDTALBgNVBAgTBGNoZW4xDTALBgNVBAcTBGNoZW4xDTALBgNVBAoTBGNoZW4xDTALBgNV\n" +
"BAsTBGNoZW4xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAOCj9+qaE/DcDtJnEpeSc0+byTO3/yM673C4sgax7n4lCnjtmhgqiwASTCOnEMRJ6llmo/M8\n" +
"+msz9i+1vE4lte7AkZ/3Wfu04BXq9wmDlVNWU3kU6TfZMUhqifTvRC6zQmfJaBdS6SSfmBslrUUC\n" +
"ntD19vvGRLPkEt05s0itG54ex41fSgA4pBtj6qpBjLMS/03fCD6y3YdL+r0dN6bDxAuLo+2flJEy\n" +
"9CrnXEzLcZ172zD+5mfvhFI7F1fF1kdjT4pNi22sap5AOFZazaK7snq03cLTchC7yBwcPCJ6IqzY\n" +
"Yw6bVb79cj6nntbTb6lsrL7wv2kR8ubtiRTrrtCP2YMCAwEAAaMhMB8wHQYDVR0OBBYEFF5ZFY02\n" +
"FejgLSsO9DOZppwUhGS4MA0GCSqGSIb3DQEBCwUAA4IBAQCNg76X3tRCtnDi7cT5M8ADMzSUlYvA\n" +
"CaVYKQ+lB3WBLuqR3wVVJ/zeSGqiR4F59cj6Oij+fk5Fu05n+0nXX/sdirf2RTW1eaA+SzPYXdgA\n" +
"0u8XJdaPu58q0GCPFpUv24ljzQEr/hZBS9HWlHmkgByecpgrrToOc3jJNIQr8g1NVO/b8RCBFyx8\n" +
"Ax+Ytp8XNGKbmMnXifBxBnhMCT0DptmZuYsTacZ5qLqEhszChYSM3drYhoNId1HlLLeQbUumbB/8\n" +
"N1BVVH2LYPTJgKdXTQAzTWiUAss/HD78fe30qI3MDrZ1h4eF+vCHqOwAOiLxQ0Rpb5oMsVCblmoR\n" +
"+ool1ljG\n" +
"-----END CERTIFICATE-----";
private static TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textview);
}
public void click(View view){
new Thread(){
@Override
public void run() {
super.run();
try {
volley();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
void volley() throws Exception{
String path = "https://10.0.2.2:8444/OkHttp/text";
ByteArrayInputStream baos = new ByteArrayInputStream(chen.getBytes());
//InputStream iStream = new FileInputStream("chen_client.jks");
InputStream iStream = getAssets().open("chen_client.bks");
SSLContext sslContext = getSSLContext(baos,iStream);
//SSLSocketFactory在HurlStack内部已经实现
//HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
HurlStack hurlStack = new HurlStack(null,sslContext.getSocketFactory());
RequestQueue queue = Volley.newRequestQueue(getApplication(),hurlStack);
//get
StringRequest request = new StringRequest(path, new Response.Listener() {
@Override
public void onResponse(String response) {
sendMsg(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
sendMsg(error.toString());
}
});
//post
/*
Map map = new HashMap<>();
map.put("userName", "183********");
map.put("password", "111111");
JSONObject object = new JSONObject(map);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, path, object, new Response.Listener() {
@Override
public void onResponse(JSONObject response) {
sendMsg(response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
sendMsg(error.toString());
}
});
*/
queue.add(request);
}
private void sendMsg(String msg){
Message message = mHandler.obtainMessage();
message.obj = msg;
mHandler.sendMessage(message);
}
SSLContext getSSLContext(InputStream cer,InputStream bks){
try{
//初始化SSLContext
SSLContext context = SSLContext.getInstance("TLS");//TLS和SSL都可以
// 1.导入证书
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(cer);
// 2.证书导入密钥库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry("srca", certificate);
// 3.把密钥库放入信任管理器
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// 4.生成信任管理器
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
//初始化keystore
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientKeyStore.load(bks, "123456".toCharArray());
//将keystore放入密钥管理器
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
//生成密钥管理器
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
// 将信任管理器设置到SSLContext
context.init(keyManagers, trustManagers, new SecureRandom());
return context;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class MainActivity extends AppCompatActivity {
static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText(msg.obj.toString());
}
};
static String chen = "-----BEGIN CERTIFICATE-----\n" +
"MIIDWTCCAkGgAwIBAgIEcWnCMTANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJDTjENMAsGA1UE\n" +
"CBMEY2hlbjENMAsGA1UEBxMEY2hlbjENMAsGA1UEChMEY2hlbjENMAsGA1UECxMEY2hlbjESMBAG\n" +
"A1UEAxMJbG9jYWxob3N0MB4XDTE3MDIxMzE0MTIzNVoXDTI2MTIyMzE0MTIzNVowXTELMAkGA1UE\n" +
"BhMCQ04xDTALBgNVBAgTBGNoZW4xDTALBgNVBAcTBGNoZW4xDTALBgNVBAoTBGNoZW4xDTALBgNV\n" +
"BAsTBGNoZW4xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAOCj9+qaE/DcDtJnEpeSc0+byTO3/yM673C4sgax7n4lCnjtmhgqiwASTCOnEMRJ6llmo/M8\n" +
"+msz9i+1vE4lte7AkZ/3Wfu04BXq9wmDlVNWU3kU6TfZMUhqifTvRC6zQmfJaBdS6SSfmBslrUUC\n" +
"ntD19vvGRLPkEt05s0itG54ex41fSgA4pBtj6qpBjLMS/03fCD6y3YdL+r0dN6bDxAuLo+2flJEy\n" +
"9CrnXEzLcZ172zD+5mfvhFI7F1fF1kdjT4pNi22sap5AOFZazaK7snq03cLTchC7yBwcPCJ6IqzY\n" +
"Yw6bVb79cj6nntbTb6lsrL7wv2kR8ubtiRTrrtCP2YMCAwEAAaMhMB8wHQYDVR0OBBYEFF5ZFY02\n" +
"FejgLSsO9DOZppwUhGS4MA0GCSqGSIb3DQEBCwUAA4IBAQCNg76X3tRCtnDi7cT5M8ADMzSUlYvA\n" +
"CaVYKQ+lB3WBLuqR3wVVJ/zeSGqiR4F59cj6Oij+fk5Fu05n+0nXX/sdirf2RTW1eaA+SzPYXdgA\n" +
"0u8XJdaPu58q0GCPFpUv24ljzQEr/hZBS9HWlHmkgByecpgrrToOc3jJNIQr8g1NVO/b8RCBFyx8\n" +
"Ax+Ytp8XNGKbmMnXifBxBnhMCT0DptmZuYsTacZ5qLqEhszChYSM3drYhoNId1HlLLeQbUumbB/8\n" +
"N1BVVH2LYPTJgKdXTQAzTWiUAss/HD78fe30qI3MDrZ1h4eF+vCHqOwAOiLxQ0Rpb5oMsVCblmoR\n" +
"+ool1ljG\n" +
"-----END CERTIFICATE-----";
private static TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textview);
}
public void click(View view){
new Thread(){
@Override
public void run() {
super.run();
try {
okhttp();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
void okhttp() throws Exception{
String path = "https://10.0.2.2:8444/OkHttp/text";
ByteArrayInputStream baos = new ByteArrayInputStream(chen.getBytes());
//InputStream iStream = new FileInputStream("chen_client.jks");
InputStream iStream = getAssets().open("chen_client.bks");
SSLManagerParams ssl = getSSLManagerParams(baos,iStream);
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(ssl.mFactory,ssl.mTrustManager)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
})
.build();
//get
Request request = new Request.Builder().get().url(path).build();
//post
/*
Map map = new HashMap<>();
map.put("userName", "183********");
map.put("password", "111111");
JSONObject jsonObject = new JSONObject(map);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),jsonObject.toString());
okhttp3.Request request = new okhttp3.Request.Builder().post(requestBody).url(path).build();
*/
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
sendMsg(e.toString());
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
sendMsg(response.body().string());
}
});
}
private void sendMsg(String msg){
Message message = mHandler.obtainMessage();
message.obj = msg;
mHandler.sendMessage(message);
}
static class SSLManagerParams{
public SSLSocketFactory mFactory;
public X509TrustManager mTrustManager;
}
SSLManagerParams getSSLManagerParams(InputStream cer,InputStream bks){
SSLManagerParams ssl = new SSLManagerParams();
try{
//初始化SSLContext
SSLContext context = SSLContext.getInstance("TLS");//TLS和SSL都可以
// 1.导入证书
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(cer);
// 2.证书导入密钥库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry("srca", certificate);
// 3.把密钥库放入信任管理器
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// 4.生成信任管理器
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
//初始化keystore
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientKeyStore.load(bks, "123456".toCharArray());
//将keystore放入密钥管理器
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
//生成密钥管理器
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
// 将信任管理器设置到SSLContext
context.init(keyManagers, trustManagers, new SecureRandom());
ssl.mFactory = context.getSocketFactory();
ssl.mTrustManager = chooseX509TrustManager(trustManagers);
return ssl;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private static X509TrustManager chooseX509TrustManager(TrustManager[] trustManagers)
{
for (TrustManager trustManager : trustManagers)
{
if (trustManager instanceof X509TrustManager)
{
return (X509TrustManager) trustManager;
}
}
return null;
}
}
好了,HPPTS全面解析到这里就结束了。以上的三种网络请求代码为了便于理解,并没有做合法性检测与封装,下面我提供了一个将三种https请求的简单封装工程。
下载:CSDN
参考:http://blog.csdn.net/lmj623565791/article/details/48129405