Android OkHttp实现HTTPS访问,支持Android 4.X系统HTTPS访问
2017-02-21 20:48
495 查看
版权声明:本文为博主原创文章,未经我的允许不得转载!
转载请标明出处: http://blog.csdn.net/guiying712/article/details/56301736 ,本文出自:【张华洋的博客】
许多网站都会介绍一个糟糕的替代解决方案,让您使用一个没用的 TrustManager。如果您这样做还不如不加密通信,因为任何人都可以在公共 WLAN 热点下,使用伪装成您的服务器的代理发送您的用户流量,通过 DNS 欺骗攻击您的用户。然后,攻击者可以记录密码和其他个人数据。此方法之所以有效是因为攻击者可以生成一个证书,且没有可以切实验证证书是否来自值得信任的来源的 TrustManager,从而使您的应用可与任何人通信。因此,不要使用不做证书校验的TrustManager,暂时性的也不行。下面是目前最完善的Https证书校验工具类,实现了服务端和客户端之间的基于身份认证的交互,并且真正实现了 TrustManger 的 checkServerTrusted() 方法,对服务器证书域名进行了强校验,另外也真正实现了 HostnameVerifier 的 verify() 方法。
自行实现的X509TrustManager,用于对服务器证书域名进行强校验:
自定义HostnameVerifier,用于校验主机名,请把”192.168.0.10”换成你们公司的主机IP:
自定义SSLSocketFactory ,实现Android 4.X 对TLSv1.1、TLSv1.2的支持
这个工具的使用方法:
最后贴上,HttpsUtil源码请点击这里:HttpsUtils源码,如果你觉得对你有帮助请顺手点个star.
另外这是我写的Android项目组件化详细实施方案 ,欢迎大家提意见。
转载请标明出处: http://blog.csdn.net/guiying712/article/details/56301736 ,本文出自:【张华洋的博客】
许多网站都会介绍一个糟糕的替代解决方案,让您使用一个没用的 TrustManager。如果您这样做还不如不加密通信,因为任何人都可以在公共 WLAN 热点下,使用伪装成您的服务器的代理发送您的用户流量,通过 DNS 欺骗攻击您的用户。然后,攻击者可以记录密码和其他个人数据。此方法之所以有效是因为攻击者可以生成一个证书,且没有可以切实验证证书是否来自值得信任的来源的 TrustManager,从而使您的应用可与任何人通信。因此,不要使用不做证书校验的TrustManager,暂时性的也不行。下面是目前最完善的Https证书校验工具类,实现了服务端和客户端之间的基于身份认证的交互,并且真正实现了 TrustManger 的 checkServerTrusted() 方法,对服务器证书域名进行了强校验,另外也真正实现了 HostnameVerifier 的 verify() 方法。
/** * @param context 上下文 * @param bksFileId "XXX.bks"文件(文件位置res/raw/XXX.bks) * @param password The certificate's password. * @return SSLParams */ public static SSLParams getSslSocketFactory(Context context, @RawRes int bksFileId, String password, String alias) { if (context == null) { throw new NullPointerException("context == null"); } SSLParams sslParams = new SSLParams(); try { // 创建一个BKS类型的KeyStore,存储我们信任的证书 KeyStore clientKeyStore = KeyStore.getInstance("BKS"); clientKeyStore.load(context.getResources().openRawResource(bksFileId), password.toCharArray()); //通过alias直接从密钥库中读取证书 Certificate rootCA = clientKeyStore.getCertificate(alias); // Turn it to X509 format. InputStream certInput = new ByteArrayInputStream(rootCA.getEncoded()); X509Certificate serverCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certInput); //关闭流 CloseUtils.closeIO(certInput); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); //用我们之前的keyStore实例初始化TrustManagerFactory,这样trustManagerFactory就会信任keyStore中的证书 trustManagerFactory.init(clientKeyStore); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, password.toCharArray()); X509TrustManager x509TrustManager = new SafeTrustManager(serverCert); //创建TLS类型的SSLContext对象,that uses our TrustManager SSLContext sslContext = SSLContext.getInstance("TLS"); //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); //Android 4.X 对TLS1.1、TLS1.2的支持 sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory()); sslParams.trustManager = x509TrustManager; return sslParams; } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | IOException | CertificateException e) { throw new AssertionError(e); } }
自行实现的X509TrustManager,用于对服务器证书域名进行强校验:
/** * 对服务器证书域名进行强校验 */ private static class SafeTrustManager implements X509TrustManager { private X509Certificate mCertificate; private SafeTrustManager(X509Certificate serverCert) { mCertificate = serverCert; } @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { if (x509Certificates == null) { throw new IllegalArgumentException("Check Server x509Certificates is null"); } if (x509Certificates.length < 0) { throw new IllegalArgumentException("Check Server x509Certificates is empty"); } try { for (X509Certificate cert : x509Certificates) { // Make sure that it hasn't expired. cert.checkValidity(); //和App预埋的证书做对比 cert.verify(mCertificate.getPublicKey()); } } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) { e.printStackTrace(); } } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }
自定义HostnameVerifier,用于校验主机名,请把”192.168.0.10”换成你们公司的主机IP:
public static HostnameVerifier getHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { if ("192.168.0.10".equals(hostname)) { return true; } else { HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); return hv.verify(hostname, session); } } }; }
自定义SSLSocketFactory ,实现Android 4.X 对TLSv1.1、TLSv1.2的支持
private static class Tls12SocketFactory extends SSLSocketFactory { private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"}; final SSLSocketFactory delegate; private Tls12SocketFactory(SSLSocketFactory base) { this.delegate = base; } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return patch(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException { return patch(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return patch(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return patch(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return patch(delegate.createSocket(address, port, localAddress, localPort)); } private Socket patch(Socket s) { //代理SSLSocketFactory在创建一个Socket连接的时候,会设置Socket的可用的TLS版本。 if (s instanceof SSLSocket) { ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION); } return s; } }
这个工具的使用方法:
HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(Utils.getContext(), R.raw.bks, "66666", "6666") okHttpClient = new OkHttpClient.Builder() .connectTimeout(30000L, TimeUnit.MILLISECONDS) .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) .hostnameVerifier(HttpsUtil.getHostnameVerifier()) .addInterceptor(new LoggerInterceptor(null, true)) .build();
最后贴上,HttpsUtil源码请点击这里:HttpsUtils源码,如果你觉得对你有帮助请顺手点个star.
另外这是我写的Android项目组件化详细实施方案 ,欢迎大家提意见。
相关文章推荐
- 在linux安装配置svn并实现支持ssl认证https安全访问方式
- Android进阶(三)android httpClient 支持HTTPS的访问方式
- 关于Android4.x系统支持TLS1.2的解决方案
- Linux系统下自建CA实现https访问
- 基于OKHttp实现对Https的支持
- android httpClient 支持HTTPS的访问方式
- Android应用程序访问linux驱动第三步:实现并向系统注册Service
- Android 4.x 在 https 协议下无法利用 okhttp 进行网络访问的临时解决办法
- CentOS7 配置Nginx支持HTTPS访问的实现方案
- 硬件访问服务4之Android硬件访问服务框架及系统函数全详细实现
- android httpClient 支持HTTPS的访问方式
- BlueStacks不仅支持x86和ARM处理器,新版BlueStacks并不是单纯的实现虚拟化,而是运行整个Android系统
- 浅析Android系统中HTTPS通信的实现
- rxandroid+okhttp下载并支持https
- [置顶] Android系统访问控制之Smack安全策略设计与实现
- android httpClient 支持HTTPS的访问方式
- Android系统中HTTPS通信的实现
- android httpClient 支持HTTPS的访问方式
- Android中实现截图保存到指定目录或者系统图片,并支持批量删除
- Android 基于OkHttp的下载,支持https,断点下载,优化下载速度