OkHttp3之Https访问(五)

一、概述

其实这篇文章理论上不限于okhttp去访问自签名的网站,不过接上篇博文了,就叫这个了。首先要了解的事,okhttp默认情况下是支持https协议的网站的,比如https://www.baidu.comhttps://github.com/hongyangAndroid/okhttp-utils等,你可以直接通过okhttp请求试试。不过要注意的是,支持的https的网站基本都是CA机构颁发的证书,默认情况下是可以信任的。

当然我们今天要说的是自签名的网站,什么叫自签名呢?就是自己通过keytool去生成一个证书,然后使用,并不是CA机构去颁发的。使用自签名证书的网站,大家在使用浏览器访问的时候,一般都是报风险警告,如下界面:使用 okhttp 进行访问时未信任的安全网站时会提示

javax.net.ssl.SSLHandshakeException: 
    java.security.cert.CertPathValidatorException: 
        Trust anchor for certification path not found.

javax.net.ssl.SSLPeerUnverifiedException: Hostname xxxx.com not verified:

二、解决办法

解决办法有两种

  • 信任所有的证书(开发测试使用)

  • 导入自签名证书

1、信任所有的证书

信任所有的证书后可以成功解决掉不能访 https 自签名地址的问题,但这样也就失去了使用自签名的意义。开发过程中可以使用这种方式屏蔽掉自签名,需要使用到无法获得证书的地址的资源时也可以使用这种方式。

实现代码

import okhttp3.OkHttpClient;

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

/**
 * 封装的支持Https连接工具类
 */
public class HttpsUtils {

    private MyTrustManager mMyTrustManager;

    private SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            mMyTrustManager = new MyTrustManager();
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{mMyTrustManager}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }

        return ssfFactory;
    }

    /**
     * 实现X509TrustManager接口
     */
    public class MyTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    /**
     * 实现HostnameVerifier接口(信任所有的 https 证书。)
     */
    private class TrustAllHostnameVerifier implements HostnameVerifier {

        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    public OkHttpClient getTrustAllClient() {
        OkHttpClient.Builder mBuilder = new OkHttpClient.Builder();
        mBuilder.sslSocketFactory(createSSLSocketFactory(), mMyTrustManager)
                .hostnameVerifier(new TrustAllHostnameVerifier());
        return mBuilder.build();
    }
}

实现步骤:

  1. 创建实现 HostnameVerifier 接口的类并重写他的verify方法使其直接返回true;

  2. 创建实现 X509TrustManager 接口的类并重写getAcceptedIssuers()使其返回 new X509Certificate[0];

  3. 构建 SSL 工厂SSLSocketFactory即上面代码中的createSSLSocketFactory()方法;

  4. 使用 OkHttpClient.Builder 中设置 sslSocketFactory(构建的工厂,实现的 TrustManager 类),此处的 TurstManager 需要保持跟 Factory 中使用的 TrustManager 是同一个实例。设置 hostnameVerifier 为构建的 HostnameVerifier;

2、导入自签名证书

信任所有证书虽然能解决不能访问 https 服务器地址的问题,但安全性被忽视掉了。显然是不符合要求的,用 https 就是为了安全性跳过 验证也就失去了他的意义了。好在我们还有其他的方法来解决----导入自签名的证书。


未完带补充。。。


赞(52) 打赏
未经允许不得转载:优客志 » JAVA开发
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏