/*
* 第一種方式:只信任當前的證書*    1.android客戶端從伺服器下載https證書,放到專案的assets檔案下     2.okhttp的固定程式碼,進行https各種配置,比如X.509,固定的模式,直接拷貝     3.設定證書,assets檔案下,按照證書的名稱讀取設定給okhttp
所以一般我們會把2,3兩部封裝成一個方法,暴露一個String引數,複製輸入證書的名稱,然後直接呼叫即可     4.接下來就是初級call物件,非同步請求,okhttp的正常使用一樣
  第二種方式:信任所有https主機的訪問         1.OkHttpClient初始化時,配置建立一個證書物件,校驗名稱,信任所有的主機,也就是信任所有https的請求
         對應所要建立的類,是固定模式,直接拷貝使用即可         2.okhttp的正常使用
 兩種方式要想看效果,需要新增okhttp的日誌攔截器方可
 提示:
     1.信任所有的伺服器地址,所有的https網址,我們去請求資料時,都會返回的有資料.
大部分公司沒有去弄證書,偷懶所以就信任所有的伺服器地址,這樣合法性保證不了,但是資料加密沒有問題.
     2.信任自己的伺服器,載入自己的證書時,只有我們自己的伺服器才會返回有資料,其他https網址就壓根不會連線
     這樣做最穩妥,下載自己的證書.校驗本地證書.
伺服器通過命令列的模式生成一個證書(java的工具類生成),然後伺服器配置這個證書,支援https,埠號443.
注意:使用日誌攔截器,要看看模擬有沒有SD卡裝置,4.1.1
* */
 
 @Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
    //只信任當前證書
certData();
     //信任所有證書
loadData();

  }
   /*
   * 信任所有證書的方法   * */
private void loadData() {
      OkHttpClient httpClient =
              new OkHttpClient.Builder()
                      .addInterceptor(new LogInterceptor())//新增okhttp日誌攔截器
//不加以下兩行程式碼,https請求不到自簽名的伺服器
.sslSocketFactory(createSSLSocketFactory())//建立一個證書物件
.hostnameVerifier(new TrustAllHostnameVerifier())//校驗名稱,這個物件就是信任所有的主機,也就是信任所有https的請求
.connectTimeout(10, TimeUnit.SECONDS)//連線超時時間
.readTimeout(10, TimeUnit.SECONDS)//讀取超時時間
.writeTimeout(10, TimeUnit.SECONDS)//寫入超時時間
.retryOnConnectionFailure(false)//連線不上是否重連,false不重連
.build();

      //提交表單,輸入的賬戶名和密碼按照伺服器定義的格式
FormBody formbody = new FormBody.Builder().add("mobile", "18612991023").add("password", "111111").build();
      Request request = new Request.Builder().url("https://www.zhaoapi.cn/user/login").post(formbody).build();
      httpClient.newCall(request).enqueue(new Callback() {
          @Override
public void onFailure(okhttp3.Call call, IOException e) {

          }

          @Override
public void onResponse(Call call, Response response) throws IOException {
              Log.d("++=====++++",""+response.body().string());
          }
      });

  }

  private static SSLSocketFactory createSSLSocketFactory() {
      SSLSocketFactory ssfFactory = null;

      try {
          SSLContext sc = SSLContext.getInstance("TLS");
          sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());

          ssfFactory = sc.getSocketFactory();
      } catch (Exception e) {
      }

      return ssfFactory;
  }

  private static class TrustAllCerts implements X509TrustManager {
      @Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
      }

      @Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

      }

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

  //信任所有的伺服器,返回true
private static class TrustAllHostnameVerifier implements HostnameVerifier {
      @Override
public boolean verify(String hostname, SSLSession session) {
          return true;
      }
  }


/*
* 信任當前證書的方法* */
private void certData() {
      //提交表單資訊
FormBody formbody = new FormBody.Builder()
              .add("mobile", "18612991023")
              .add("password", "111111")
              .build();
      //請求物件初始化的設定,請求Url,請求方式,表單資訊
Request request = new Request.Builder().url("https://www.zhaoapi.cn/user/login").post(formbody).build();
      //setCard(),用時直接拷貝,app帶證書驗證
setCard("zhaoapi_server.cer").newCall(request).enqueue(new Callback() {
          @Override
public void onFailure(Call call, IOException e) {

          }

          @Override
public void onResponse(Call call, Response response) throws IOException {
              Log.d("+++++++",""+response.body().string());
          }
      });
  }
  /**
   * app帶證書驗證的方法,使用是修改一下zhaoapi_server.cer即可,其他都是固定的模式,直接拷貝
*/
public OkHttpClient setCard(String zhenshu) {
      OkHttpClient.Builder builder = new OkHttpClient.Builder();
      try {
          //https固定模式,X.509是固定的模式
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
          //關聯證書的物件
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
          keyStore.load(null);
          String certificateAlias = Integer.toString(0);
          //核心邏輯,信任什麼證書,Assets讀取拷貝進去的證書
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(getAssets().open(zhenshu)));
          SSLContext sslContext = SSLContext.getInstance("TLS");
          //信任關聯器
final TrustManagerFactory trustManagerFactory =
                  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
          //初始化證書物件
trustManagerFactory.init(keyStore);
          sslContext.init
                  (
                          null,
                          trustManagerFactory.getTrustManagers(),
                          new SecureRandom()
                  );
          builder.sslSocketFactory(sslContext.getSocketFactory());
          builder.addInterceptor(new LogInterceptor());
          builder.hostnameVerifier(new HostnameVerifier() {
              @Override
public boolean verify(String s, SSLSession sslSession) {
                  return true;
              }
          });
      } catch (Exception e) {
          e.printStackTrace();
      }
      return builder.build();
  }