参考资料
- 简单使用get http://blog.youkuaiyun.com/qq_23077365/article/details/52164375
- 添加请求头和上传图片 http://blog.youkuaiyun.com/linzhenxiang123/article/details/53956435
- 发送请求中添加身份验证 http://www.cnblogs.com/guanghuiz/p/5476972.html
- SSL双向验证 http://blog.youkuaiyun.com/u012874222/article/details/50339259
- 如何使用@body发送post http://www.cnblogs.com/fengfenghuifei/p/6038309.html
生成两个bks文件(如何生成可以参考以下链接,讲的比较详细,但是如果只是想知道如何使用,看生成部分就可以了),放入assets文件夹下:
Android HTTPS 自制证书实现双向认证(OkHttp + Retrofit + Rxjava)在build.gradle添加如下包:
dependencies { compile 'io.reactivex:rxjava:1.2.3' compile 'io.reactivex:rxandroid:1.2.1' /** * Retrofit, adapter-rxjava, converter-gson must be the same version!!! * ↑ 就是说版本包得一致才行噻~ */ compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' }
- 在java/包名下,新建一个文件夹(我的叫retrofit)。
新建一个UnSafeHostnameVerifier放到retrofit下,内容如下:
public class UnSafeHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { return true; } }
新建一个SSLHelper(这个其实所有双向认证用的都是一样的,并不是专门针对Retrofit的)放到retrofit下,内容如下:
public class SSLHelper { private final static String CLIENT_PRI_KEY = "hengtiansoft.com.bks"; private final static String TRUSTSTORE_PUB_KEY = "client-truststore.bks"; private final static String CLIENT_BKS_PASSWORD = "hT118InsIgmA"; private final static String TRUSTSTORE_BKS_PASSWORD = "wso2carbon"; private final static String KEYSTORE_TYPE = "BKS"; private final static String PROTOCOL_TYPE = "TLS"; private final static String CERTIFICATE_STANDARD = "X509"; public static SSLSocketFactory getSSLCertifcation(Context context) { SSLSocketFactory sslSocketFactory = null; try { // 服务器端需要验证的客户端证书,其实就是客户端的keystore KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); // 客户端信任的服务器端证书 KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE); //读取证书 InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY); InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY); //加载证书 keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray()); trustStore.load(tsIn, TRUSTSTORE_BKS_PASSWORD.toCharArray()); ksIn.close(); tsIn.close(); //初始化SSLContext SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_STANDARD); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_STANDARD); trustManagerFactory.init(trustStore); keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray()); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); sslSocketFactory = sslContext.getSocketFactory(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } return sslSocketFactory; } public static OkHttpClient genericClient() { OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request() .newBuilder() .addHeader("Authentication-Token", "d90d790cf80d1078750e840a8922c02b-1376208214") .build(); return chain.proceed(request); } }) .build(); return httpClient; } }
根据业务逻辑,新建一个BaseResponse在retrofit文件夹下,内容如下:
public class BaseResponse <T> { public static String UNKNOWN_ERROR = "未知错误"; private boolean success; private String errorCode; private T data; private String msg; public BaseResponse() { } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getErrorCode() { return errorCode; } public void setErrorCode(String errorCode) { this.errorCode = errorCode; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
根据业务逻辑,新建一个数据传输类(按照接口来写,在此选取一个Token类),内容如下:
public class Token { private String TGT; private String token; public String getTGT() { return TGT; } public void setTGT(String TGT) { this.TGT = TGT; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } }
根据业务返回,新建一个CallBack,内容如下:
public abstract class RetrofitCallBack<T extends BaseResponse> implements Callback<T> { @Override public void onResponse(Call<T> call, Response<T> response) { if (response.raw().code() == 200) {//200是服务器有合理响应 if (response.body() != null) { onBizSuccess(response.body()); } else { onBizFail(originResult, response.body(), response.raw().code()); } } else {//失败响应 onFailure(call, new RuntimeException("response error,detail = " + response.raw().toString())); } } @Override public void onFailure(Call<T> call, Throwable ex) {//网络问题会走该回调 if (ex instanceof SocketTimeoutException) { // } else if (ex instanceof ConnectException) { // } else if (ex instanceof RuntimeException) { // } onFail(ex); } public abstract void onBizSuccess(T result); public abstract void onBizFail(String originResult, T result, int returnCode); public abstract void onFail(Throwable ex); }
根据业务模块区分,新建一个service(我在这里选取一个AuthService),内容如下:
public interface AuthService { /** * 获取token * * @param appKey * @param token * @param requestBody * @return */ @POST("/services/htmf-auth/getToken") Call<BaseResponse<Token>> getToken(@Header("AppKey") String appKey, @Body RequestBody requestBody); }
新建一个RetrofitClient类放在retrofit下,内容如下:
public class RetrofitClient { public static final String HTTP_CACHE_DIR = "DemoCache"; //ip地址 public static final String BASE_URL = "https://xxx.xxx.com"; /** * 网络请求接口包装类,可细分多个Service **/ public AuthService authService; public static final long DEFAULT_TIMEOUT = 7676l; private static Context mContext; /** * 在访问HttpMethods时创建延迟加载的单例 **/ private static class SingletonHolder { private static final RetrofitClient INSTANCE = new RetrofitClient(mContext); } // 获取单例 public static RetrofitClient getInstance(Context context) { if (context != null) { mContext = context; } return SingletonHolder.INSTANCE; } private RetrofitClient(Context context) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(SSLHelper.getSSLCertifcation(context)); builder.hostnameVerifier(new UnSafeHostnameVerifier()); // 网络请求的缓存机制,无网络也能显示数据 File cacheFile = new File(context.getCacheDir(), HTTP_CACHE_DIR); Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); builder.addNetworkInterceptor(new HttpCacheInterceptor()); // 保持请求是同一个cookie CookieManager cookieManager = new CookieManager(); cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); // 其他设置 builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) .retryOnConnectionFailure(true)// 错误重连 // .addInterceptor(addQueryParameterInterceptor)// 公共参数 .cache(cache);// 缓存目录 // .cookieJar(new JavaNetCookieJar(cookieManager)); OkHttpClient okHttpClient = builder.build(); Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").serializeNulls().create(); Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient)// okhttp的实现 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())// RxJava支持 .addConverterFactory(GsonConverterFactory.create(gson))// Gson支持 .baseUrl(BASE_URL)// 请求地址 .build(); // 可使用ServiceFactory细分接口服务 authService = retrofit.create(AuthService.class); eventAnalyticService = retrofit.create(EventAnalyticService.class); } class HttpCacheInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!NetWorkUtil.isNetConnected(mContext)) { request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); } Response originalResponse = chain.proceed(request); if (NetWorkUtil.isNetConnected(mContext)) { // 有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置 String cacheControl = request.cacheControl().toString(); // int maxAge = 0; return originalResponse.newBuilder() .header("Cache-Control", cacheControl)//"public, max-age="+maxAge .removeHeader("Pragma")// 清除头信息,因为服务器如果不支持会返回一些干扰信息,不清除下面无法生效 .build(); } else { int maxStale = 60 * 60 * 24 * 28;// 2419200 return originalResponse.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .removeHeader("Pragma") .build(); } } }
已经可以调用啦~
Map<String, String> values="";//此处的value值自己添加 String postTokenStr = JSON.toJSONString(values); RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), postTokenStr); RetrofitClient.getInstance(context).authService.getToken("", "", body).enqueue(new RetrofitCallBack<BaseResponse<Token>>() { @Override public void onBizSuccess(BaseResponse<Token> result) { } @Override public void onBizFail(String originResult, BaseResponse<Token> result, int returnCode) { } @Override public void onFail(Throwable ex) { } });
Android 带双向认证的Retrofit基础使用
最新推荐文章于 2024-06-13 18:14:37 发布