【Android】支持https接口调用的简单证书校验
16lz
2021-01-26
我们在做https接口支持时,用到了X509证书。然后针对X509的证书验证,线下环境不做校验,线上环境仅仅做单向的hostname校验。完善的校验应该包括客户端和服务端的证书校验。
package com.xxx.utils;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.Certificate;import java.security.cert.CertificateParsingException;import java.security.cert.X509Certificate;import java.util.Arrays;import java.util.Collection;import java.util.List;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLPeerUnverifiedException;import javax.net.ssl.SSLSession;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;public class HttpsTrustManager implements X509TrustManager { private static TrustManager[] trustManagers; private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {}; @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { //验证客户端证书,不通过则抛出异常 } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { //验证服务端证书,不通过则抛出异常 } @Override public X509Certificate[] getAcceptedIssuers() { return _AcceptedIssuers; } public static void allowAllSSL() { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { // FIXME 线上要做HTTPS证书信息验证 boolean isTrust = false; //如果线下则默认不校验,isOnline自己做控制 if (!isOnline) { isTrust = true; LogUtil.d("线下环境,证书不校验。"); } else { try { //获得证书 Certificate[] certificates = session.getPeerCertificates(); if (certificates != null && certificates.length > 0) { Certificate certificate = certificates[0]; //做X509证书信息获取 if (certificate instanceof X509Certificate) { X509Certificate x509Certificate = (X509Certificate) certificate; Collection> subjectAlternativeNames = x509Certificate .getSubjectAlternativeNames(); //获得证书信息 String names = Arrays .deepToString(subjectAlternativeNames.toArray()); //校验host信息 isTrust = names.contains(hostname); } } } catch (SSLPeerUnverifiedException e) { LogUtil.e("on error when verify SSL." + e.getMessage()); } catch (CertificateParsingException e) { LogUtil.e("on error when verify SSL." + e.getMessage()); } } if (!isTrust) { LogUtil.d("证书校验不通过,请核查~(hostname=" + hostname + ")"); } return isTrust; } }); SSLContext context = null; if (trustManagers == null) { trustManagers = new TrustManager[] { new HttpsTrustManager() }; } try { context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, new SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); }}
然后在网络请求之前调用如下代码:
//添加https支持 HttpsTrustManager.allowAllSSL();
更多相关文章
- Android智能POS应用开发学习清单
- Android中图像变换Matrix的原理、代码验证和应用(二)
- Android(安卓)表单验证框架:AValidations
- java Android(安卓)OKHttp HTTPS 请求证书验证 PEM证书(1)
- Android实现发送短信验证码倒计时功能示例
- Android(安卓)指纹笔记
- Android(安卓)AppWidget实例验证
- Android如何通过手机自动获取短信验证码
- Android(安卓)7.0及以上版本 使用fillder抓取https请求