转载请注明出处:http://blog.csdn.net/heisunfly/article/details/78951247
前端时间公司的项目是自签名的网站,用okhttp在5.0以下的手机上访问不了接口,网上查了一些资料自己总结了一下,做了出来。目前一般两种方式一种是配置证书,一种是忽略证书。
一 配置自己的证书
关于配置自己的证书我是参照鸿神的https做的,附上博客地址:http://blog.csdn.net/lmj623565791/article/details/48129405大家可以去看看里面有简单介绍https,我的大部分代码是参照这篇博客,不过由于okhttp的版本更新了一些方法可能写法存在区别,我自己找了些资料还是实现了,另外鸿神的这边博客是结合他之前自己封装的okhttp库写的,我这里把代码提出来方便大家用在自己项目上或者自己去再去封装。
首先导出自己的证书,鸿神的博客有介绍这里就不说了,把自己的证书放入assets目录下,没有的话自己在main下建个文件夹就好了。
这里也可以吧证书配置的方法写成单例的直接在Application中调用,这样就不用每一次网络请求都去写入一次证书,我这里就方便一次写在这里大家好看。
public class HttpUtils { //get请求 public static void getOkHttpRequeset(String url, Callback callback, Context context) { OkHttpClient client = null; try { client = new OkHttpClient.Builder().sslSocketFactory(setCertificates(context.getAssets().open("xxxx.cer"))).build(); Request request = new Request.Builder().url(url).build(); client.newCall(request).enqueue(callback); } catch (IOException e) { e.printStackTrace(); } } //post请求 public static void postOkHttpRequest(String url, RequestBody requestBody,Context context, Callback callback) { OkHttpClient client = null; try { client = new OkHttpClient.Builder().sslSocketFactory(setCertificates(context.getAssets().open("xxxx.cer"))).build(); if (requestBody != null) { Request request = new Request.Builder().url(url).post(requestBody).build(); client.newCall(request).enqueue(callback); } else { RequestBody requestBody1 = new FormBody.Builder().build(); Request request = new Request.Builder().url(url).post(okhttp3.internal.Util.EMPTY_REQUEST).build(); client.newCall(request).enqueue(callback); } } catch (IOException e) { e.printStackTrace(); } } //配置自己的证书的方法 // context.getAssets().open("xxxx.cer"))传入这个值,xxxx.cer代表你的证书 public static SSLSocketFactory setCertificates(InputStream... certificates) { try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; for (InputStream certificate : certificates) { String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); try { if (certificate != null) certificate.close(); } catch (IOException e) { } } SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); sslContext.init ( null, trustManagerFactory.getTrustManagers(), new SecureRandom() ); return sslContext.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return null; } }
使用:url填入你的地址,请求第二个参数是requesbody没有就传null
public class OkhttpsActivity extends AppCompatActivity { //你的请求地址 private String url = ""; private TextView textView; private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_okhttps); textView = findViewById(R.id.textView); context = this; HttpUtils.postOkHttpRequest(url, null,context, new Callback() { @Override public void onFailure(Call call, IOException e) { runOnUiThread(new Runnable() { @Override public void run() { textView.setText("失败"); } }); } @Override public void onResponse(Call call, Response response) throws IOException { final String result = response.body().string(); runOnUiThread(new Runnable() { @Override public void run() { textView.setText(result); } }); } }); } }
二 忽略证书
这个方法比较简单直接,我就用的忽略,因为存在证书会经常改变的情况。
public class HttpUtils { public static void getOkHttpRequeset(String url, Callback callback) { OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(createSSLSocketFactory()).build(); Request request = new Request.Builder().url(url).build(); client.newCall(request).enqueue(callback); } public static void postOkHttpRequest(String url, RequestBody requestBody, Callback callback) { OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(createSSLSocketFactory()).build(); if (requestBody != null) { Request request = new Request.Builder().url(url).post(requestBody).build(); client.newCall(request).enqueue(callback); } else { RequestBody requestBody1 = new FormBody.Builder().build(); Request request = new Request.Builder().url(url).post(okhttp3.internal.Util.EMPTY_REQUEST).build(); client.newCall(request).enqueue(callback); } } @SuppressLint("TrulyRandom") public static SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory sSLSocketFactory = null; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new TrustAllManager()}, new SecureRandom()); sSLSocketFactory = sc.getSocketFactory(); } catch (Exception e) { } return sSLSocketFactory; } public static class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }使用和之前的一样就是少传入一个context参数即可。