赞
踩
在android的开发过程中,我们目前常用到的网络请求框架基本都是基于Okhttp,而Https网络通信在APP的开发中也被应用的越来越多,Okhttp默认是支持https网络请求的,但是支持的Https网站必须是CA机构认证了的,对于自签名的网址,还是不能访问的,访问直接抛出如下异常信息:
onFailure: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
针对https的处理,目前主要有两种方式:
这个方式实现起来简单,但是因为信任了全部证书,会有一定的风险!使用者需注意,下面了解一下具体的实现:
1.新建MyTrustManager实现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];}
}
2.创建一个方法,用于获取SSLSocketFactory:
private static SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return ssfFactory;
}
3.OKhttpClient的配置:
static {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.sslSocketFactory(createSSLSocketFactory());
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
mOkHttpClient = builder.build();
}
将其封装到Okhttp工具类中,完整代码如下所示:
public class OkhttpUtil { public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static final MediaType JSON2 = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"); private static OkHttpClient mOkHttpClient = new OkHttpClient(); private static SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory ssfFactory = null; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom()); ssfFactory = sc.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return ssfFactory; } static { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(30, TimeUnit.SECONDS); builder.sslSocketFactory(createSSLSocketFactory()); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); mOkHttpClient = builder.build(); } public static Response execute(Request request) throws IOException { return mOkHttpClient.newCall(request).execute(); } public static void enqueue(Request request, Callback responseCallback) { mOkHttpClient.newCall(request).enqueue(responseCallback); } public static void enqueue(Request request) { mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }); } public static String getStringFromServer(String url) throws IOException { Request request = new Request.Builder().url(url).build(); Response response = execute(request); if (response.isSuccessful()) { String responseUrl = response.body().string(); return responseUrl; } else { throw new IOException("Unexpected code " + response); } } private static final String CHARSET_NAME = "UTF-8"; public static String formatParams(List<BasicNameValuePair> params) { return URLEncodedUtils.format(params, CHARSET_NAME); } public static String attachHttpGetParams(String url, List<BasicNameValuePair> params) { return url + "?" + formatParams(params); } public static String attachHttpGetParam(String url, String name, String value) { return url + "?" + name + "=" + value; } public static String post(String url, FormBody body) throws IOException { Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = mOkHttpClient.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } public static String post(String url, JSONObject jsonObject) throws IOException { RequestBody body = RequestBody.create(JSON, jsonObject.toString()); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = mOkHttpClient.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } public static String postFrom2Json(String url, JSONObject jsonObject) throws IOException { RequestBody body = RequestBody.create(JSON2, jsonObject.toString()); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = mOkHttpClient.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } /** * get 方式请求 异步线程中执行 * * @param url 请求地址 * @return 请求结果 */ public static String get(String url) throws IOException { Request request = new Request.Builder().url(url).build(); Response response = mOkHttpClient.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } /** * get 方式请求 异步线程中执行 * * @param url 请求地址 * @return 请求结果 */ public static void get(String url, Callback responseCallback) { Request request = new Request.Builder().url(url).build(); mOkHttpClient.newCall(request).enqueue(responseCallback); } }
至此,客户端默认信任全部证书的实现方式就基本实现了。
##WebView中Https的处理
当前很多应用都使用webview加载H5页面,如果服务端采用的是可信CA颁发的证书,在 webView.setWebViewClient(webviewClient) 时重载 WebViewClient的onReceivedSslError() ,如果出现证书错误,直接调用handler.proceed()会忽略错误继续加载证书有问题的页面;如果调用handler.cancel()可以终止加载证书有问题的页面;证书出现问题了,可以提示用户风险,让用户选择加载与否,如果是需要安全级别比较高,可以直接终止页面加载,提示用户网络环境有风险。handler.proceed方法是接受所有的证书,和上文所说的一样当然也是不安全的一种方法。
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
view.getSettings().setJavaScriptEnabled(true);
}
对自签名网站进行处理网络上有较多的介绍,这里推荐鸿洋的Https相关完全解析 当OkHttp遇到Https 文中对处理的方式有详细的介绍,本文不再做单独的说明处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。