引入HTTPS是为了解决HTTP所带来的三个问题:
前面博客中写了如何绕过证书访问,那是不安全的访问方式,容易受到中间人攻击,所以客户端需要做双向证书校验,来保证客户端的合法性。
private static SSLSocketFactory setCertificates(InputStream... certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
if (certificate != null) {
certificate.close();
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
域名校验需要自己设置一个trustHosts数组,当前访问域名匹配这个数组中的一条,即可返回true,否则返回false。
//获取HostnameVerifier
public static HostnameVerifier getHostnameVerifier(final JSONArray trustHosts) {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession sslSession) {
if (trustHosts == null || trustHosts.length() == 0) {
return false;
}
try {
for (int i = 0; i < trustHosts.length(); i++) {
String trustHost = trustHosts.getString(i);
if (host.equalsIgnoreCase(trustHost)) {
return true;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
};
return hostnameVerifier;
}
//获取这个SSLSocketFactory
public static SSLSocketFactory getSSLSocketFactory(InputStream cerIn) {
try {
SSLSocketFactory factory = setCertificates(cerIn);
return factory;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
JSONArray trustHosts= new JSONArray();
jsonArray.put("192.169.15.110");
jsonArray.put("192.169.15.111");
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(SSLSocketCert.getSSLSocketFactory(context.getAssets().open("jetty.crt")));
builder.hostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
JSONArray trustHosts= new JSONArray();
jsonArray.put("192.169.15.110");
jsonArray.put("192.169.15.111");
URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
((HttpsURLConnection) conn).setSSLSocketFactory(SSLSocketCert.getSSLSocketFactory(context.getAssets().open("jetty.crt")));
((HttpsURLConnection) conn).setHostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
上面是将证书放到Android工程的assets
下,我们也可以将证书的内容导出来放到程序中
private String CER_STR = "-----BEGIN CERTIFICATE-----\n" +
"MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn\n" +
"BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X\n" +
"DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp\n" +
"bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3\n" +
"DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2\n" +
"9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6\n" +
"D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle\n" +
"tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov\n" +
"LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt\n" +
"x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV\n" +
"23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ\n" +
"og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==\n" +
"-----END CERTIFICATE-----";
然后再调用
JSONArray trustHosts= new JSONArray();
jsonArray.put("192.169.15.110");
jsonArray.put("192.169.15.111");
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(SSLSocketCert.getSSLSocketFactory(new Buffer().writeUtf8(CER_STR).inputStream()));
builder.hostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
工具类上传地址
https://download.csdn.net/download/u010982507/10905059
学习参考
https://blog.csdn.net/lmj623565791/article/details/48129405