版权声明:本文为延成原创文章,转载请标明出处
首先导包
implementation 'com.squareup.okhttp3:okhttp:3.12.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0' implementation 'com.squareup.retrofit2:retrofit:2.5.0' implementation 'com.squareup.retrofit2:converter-gson:2.5.0' implementation 'com.squareup.retrofit2:converter-scalars:2.5.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'Retrofit工具类的封装RetrofitHelper.calss
/** * @author Mr.release * @create 2019/3/29 * @Describe */ public class RetrofitHelper { private static final String HEAD_LINE_NEWS = "T1348647909107"; private static OkHttpClient.Builder builder; static { initOkHttpClient(); } private static void initOkHttpClient() { if (builder == null) { synchronized (RetrofitHelper.class) { if (builder == null) { HttpsSSLUtils.SSLParams sslParams = HttpsSSLUtils.getSslSocketFactory(); HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); if (BuildConfig.DEBUG) { interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); } else { interceptor.setLevel(HttpLoggingInterceptor.Level.NONE); } Cache cache = new Cache(new File(App.getInstance().getCacheDir(), "HttpCache"), 1024 * 1024 * 10); builder = new OkHttpClient.Builder() .cache(cache) .addInterceptor(interceptor) .addInterceptor(new headerIntercepteor()) .addNetworkInterceptor(new CacheInterceptor()) .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) .retryOnConnectionFailure(true) .connectTimeout(30, TimeUnit.SECONDS) .writeTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS); } } } } private static <T> T createApi(String baseUrl, Class<T> cls) { Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .baseUrl(baseUrl) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) // .addConverterFactory(StringConverterFactory.create()) .build(); return retrofit.create(cls); } private static NewsServiceApi createNewsServiceApi() { return createApi(BaseURL.NEWS_HOST, NewsServiceApi.class); } private static RecommendServiceApi createRecommendServiceApi() { return createApi(BaseURL.RECOMMEND_HOST, RecommendServiceApi.class); } /** * 打印返回的json数据拦截器 */ private static class headerIntercepteor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { final Request request = chain.request(); Buffer requestBuffer = new Buffer(); if (request == null) throw new RuntimeException("Request返回值不能为空"); RequestBody requestBody = request.body(); if (requestBody != null) requestBody.writeTo(requestBuffer); else Logger.d("request.body() == null"); //打印url信息 Logger.w(request.url() + (requestBody != null ? "?" + _parseParams(requestBody, requestBuffer) : "")); final Response response = chain.proceed(request); if (response == null) { throw new RuntimeException("Response返回值不能为空"); } return response; } } @NonNull private static String _parseParams(RequestBody body, Buffer requestBuffer) throws UnsupportedEncodingException { if (body.contentType() != null && !body.contentType().toString().contains("multipart")) { return URLDecoder.decode(requestBuffer.readUtf8(), "UTF-8"); } return "null"; } private static class UserAgentInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Request requestWithUserAgent = originalRequest.newBuilder() .removeHeader("User-Agent") .addHeader("User-Agent", BaseURL.COMMON_UA_STR) .build(); return chain.proceed(requestWithUserAgent); } } private static class CacheInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 有网络时 设置缓存超时时间1个小时 int maxAge = 60 * 60; // 无网络时,设置超时为1周 int maxStale = 60 * 60 * 24 * 7; Request request = chain.request(); if (CommonUtil.isNetworkAvailable(App.getInstance())) { //有网络时只从网络获取 request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build(); } else { //无网络时只从缓存中读取 request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); } Response response = chain.proceed(request); if (CommonUtil.isNetworkAvailable(App.getInstance())) { response = response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { response = response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return response; } }HttpsSSLUtils.calss
/** * @author Mr.release * @create 2019/3/29 * @Describe */ public class HttpsSSLUtils { public static class SSLParams { public SSLSocketFactory sSLSocketFactory; public X509TrustManager trustManager; } public static SSLParams getSslSocketFactory() { return getSslSocketFactoryBase(null, null, null); } /** * https单向认证 * 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证 */ public static SSLParams getSslSocketFactory(X509TrustManager trustManager) { return getSslSocketFactoryBase(trustManager, null, null); } /** * https单向认证 * 用含有服务端公钥的证书校验服务端证书 */ public static SSLParams getSslSocketFactory(InputStream... certificates) { return getSslSocketFactoryBase(null, null, null, certificates); } /** * https双向认证 * bksFile 和 password -> 客户端使用bks证书校验服务端证书 * certificates -> 用含有服务端公钥的证书校验服务端证书 */ public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) { return getSslSocketFactoryBase(null, bksFile, password, certificates); } /** * https双向认证 * bksFile 和 password -> 客户端使用bks证书校验服务端证书 * X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可 */ public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) { return getSslSocketFactoryBase(trustManager, bksFile, password); } private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) { SSLParams sslParams = new SSLParams(); try { KeyManager[] keyManagers = prepareKeyManager(bksFile, password); TrustManager[] trustManagers = prepareTrustManager(certificates); X509TrustManager manager; if (trustManager != null) { //优先使用用户自定义的TrustManager manager = trustManager; } else if (trustManagers != null) { //然后使用默认的TrustManager manager = chooseTrustManager(trustManagers); } else { //否则使用不安全的TrustManager manager = UnSafeTrustManager; } // 创建TLS类型的SSLContext对象, that uses our TrustManager SSLContext sslContext = SSLContext.getInstance("TLS"); // 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 // 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书 sslContext.init(keyManagers, new TrustManager[]{manager}, null); // 通过sslContext获取SSLSocketFactory对象 sslParams.sSLSocketFactory = sslContext.getSocketFactory(); sslParams.trustManager = manager; return sslParams; } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); } catch (KeyManagementException e) { throw new AssertionError(e); } } private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) { try { if (bksFile == null || password == null) return null; KeyStore clientKeyStore = KeyStore.getInstance("BKS"); clientKeyStore.load(bksFile, password.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(clientKeyStore, password.toCharArray()); return kmf.getKeyManagers(); } catch (Exception e) { e.printStackTrace(); } return null; } private static TrustManager[] prepareTrustManager(InputStream... certificates) { if (certificates == null || certificates.length <= 0) return null; try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); // 创建一个默认类型的KeyStore,存储我们信任的证书 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; for (InputStream certStream : certificates) { String certificateAlias = Integer.toString(index++); // 证书工厂根据证书文件的流生成证书 cert Certificate cert = certificateFactory.generateCertificate(certStream); // 将 cert 作为可信证书放入到keyStore中 keyStore.setCertificateEntry(certificateAlias, cert); try { if (certStream != null) certStream.close(); } catch (IOException e) { e.printStackTrace(); } } //我们创建一个默认类型的TrustManagerFactory TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); //用我们之前的keyStore实例初始化TrustManagerFactory,这样tmf就会信任keyStore中的证书 tmf.init(keyStore); //通过tmf获取TrustManager数组,TrustManager也会信任keyStore中的证书 return tmf.getTrustManagers(); } catch (Exception e) { e.printStackTrace(); } return null; } private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) { for (TrustManager trustManager : trustManagers) { if (trustManager instanceof X509TrustManager) { return (X509TrustManager) trustManager; } } return null; } /** * 为了解决客户端不信任服务器数字证书的问题,网络上大部分的解决方案都是让客户端不对证书做任何检查, * 这是一种有很大安全漏洞的办法 */ public static X509TrustManager UnSafeTrustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } }; /** * 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配, * 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。 * 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true */ public static HostnameVerifier UnSafeHostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; }HttpUtils.calss
/** * @author Mr.release * @create 2019/8/2 * @Describe */ public class HttpUtils { @SuppressLint("CheckResult") public static <T> void ext(Flowable<T> flowable, IView view, boolean isShowLoading) { flowable.compose(RxUtil.rxSchedulerHelper()) .doOnSubscribe(new Consumer<Subscription>() { @Override public void accept(Subscription subscription) throws Exception { if (isShowLoading) view.showLoading(); } }) .as(RxUtil.bindLifecycle((LifecycleOwner) view)) .subscribeWith(new CommonSubscriber<T>() { @Override protected void _onNext(T bean) { Logger.d("_onNext: " + bean); view.loadData(bean); } @Override protected void _onError(String message) { Logger.d("_onError: " + message); if (isShowLoading) view.showError(); else view.showError(App.getInstance().getString(R.string.data_error)); } @Override protected void _onComplete() { view.hideLoading(); } }); } }