Android忽略https验证/自定义https验证方法 okhttp+Retrofit+https
直接上代码了,看不太明白的看下我上一篇文章 https://blog.csdn.net/u011511057/article/details/103825285
public class HttpsDemoActivity extends AppCompatActivity {
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HttpsUtils.initSslSocketFactoryCustomTrustManager(getApplication());//根据实际需求初始化
//创建OkHttpClient.Builder
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.sslSocketFactory(HttpsUtils.sSLSocketFactory, HttpsUtils.myTrustManager)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
if(HttpsUtils.cando){
return true;//通过
}else{
return false;//不通过
}
}
});//设置ssl验证
//创建Retrofit
retrofit = new Retrofit.Builder()
.baseUrl("https://*****.com")
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create()) //返回内容的转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //请求Call的转换器
.build();
}
}
下面类的方法 如果只想了解如何自定义验证和如何忽略验证只需要看initSslSocketFactoryCustomTrustManager方法
其他方法的用法参照我上一篇文章 https://blog.csdn.net/u011511057/article/details/103825285
/**
* 提供了多种初始化方法看自己情况
* 双向验证initSslSocketFactory
* 单向验证bks证书initSslSocketFactorySingle 至于bks证书的生成方式自行百度很多
* 单向验证crt证书initSslSocketFactorySingleBuyCrt
* 自定义验证方法initSslSocketFactoryCustomTrustManager
*/
public class HttpsUtils {
private static final String KEY_STORE_TYPE_BKS = "bks";
private static final String KEY_STORE_TYPE_P12 = "PKCS12";
public static final String KEY_STORE_PASSWORD = "123456";//P12文件密码
public static final String BKS_STORE_PASSWORD = "123456";//BKS文件密码
public static SSLSocketFactory sSLSocketFactory;
public static X509TrustManager trustManager;
public static X509TrustManager myTrustManager;
public static boolean cando = true;//自定义验证时是否通过验证
/**
* 双向校验中SSLSocketFactory X509TrustManager 参数的生成
* @param application
*/
public static void initSslSocketFactory(Application application) {
try {
InputStream bksStream = application.getAssets().open("xxxx.bks");//客户端信任的服务器端证书流
InputStream p12Stream = application.getAssets().open("xxxx.p12");//服务器需要验证的客户端证书流
// 客户端信任的服务器端证书
KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
// 服务器端需要验证的客户端证书
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
try {
trustStore.load(bksStream, BKS_STORE_PASSWORD.toCharArray());//加载客户端信任的服务器证书
keyStore.load(p12Stream, KEY_STORE_PASSWORD.toCharArray());//加载服务器信任的客户端证书
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
try {
bksStream.close();
p12Stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());//生成服务器用来校验客户端真实性的KeyManager
//初始化SSLContext
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 单向校验中SSLSocketFactory X509TrustManager 参数的生成
* 通常单向校验一般都是服务器不校验客户端的真实性,客户端去校验服务器的真实性
* @param application
*/
public static void initSslSocketFactorySingle(Application application) {
try {
InputStream bksStream = application.getAssets().open("xxxx.bks");//客户端信任的服务器端证书流
// 客户端信任的服务器端证书
KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
try {
trustStore.load(bksStream, BKS_STORE_PASSWORD.toCharArray());//加载客户端信任的服务器证书
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
try {
bksStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager
SSLContext sslContext = SSLContext.getInstance("TLSv1", "AndroidOpenSSL");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
//初始化SSLContext
sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 单向校验中,通过crt格式的证书生成SSLSocketFactory X509TrustManager 参数的生成
* 通常在Android中,客户端用于校验服务器真实性的证书是支持BKS格式的,但是往往后台给的证书都是crt格式的
* 当然我们可以自己生成BKS,但是想更方便一些我们也是可以直接使用crt格式的证书的
* @param application
*/
public static void initSslSocketFactorySingleBuyCrt(Application application) {
try {
InputStream crtStream = application.getAssets().open("xxxx.crt");//客户端信任的服务器端证书流
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(crtStream);
String keyStoreType = KeyStore.getDefaultType();
KeyStore trustStore = KeyStore.getInstance(keyStoreType);
try {
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", ca);
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
try {
crtStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager
SSLContext sslContext = SSLContext.getInstance("TLSv1", "AndroidOpenSSL");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
//初始化SSLContext
sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 自定义客户端校验过程
* @param application
*/
public static void initSslSocketFactoryCustomTrustManager(Application application){
try {
InputStream p12Stream = application.getAssets().open("xxxx.p12");//服务器需要验证的客户端证书流
// 服务器端需要验证的客户端证书
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
try {
keyStore.load(p12Stream, KEY_STORE_PASSWORD.toCharArray());//加载服务器信任的客户端证书
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
try {
p12Stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
myTrustManager = new X509TrustManager() {//初始化自定义TrustManager
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//todo 在此处自定义校验服务器证书方法,如果想忽略验证此处什么都不写即可
// if(通过验证){
// cando = true;
// }else(没有通过验证){
// cando = false;
// }
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());//生成服务器用来校验客户端真实性的KeyManager
//初始化SSLContext
sslContext.init(keyManagerFactory.getKeyManagers(),new TrustManager[]{myTrustManager}, null);
sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory
} catch (Exception e) {
e.printStackTrace();
}
}
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
}