okhttp3.x+retrofit2.x post請求加密 (單一類型參數 使用@Field)json
public class XApi { private static final int READ_TIME_OUT = 10; private static final int CONNECT_TIME_OUT = 20; private static XApi instance = null; private XApi() { } public static XApi getInstance() { if (instance == null) { synchronized (XApi.class) { if (instance == null) { return new XApi(); } } } return instance; } public Retrofit getRetrofit(String baseUrl) { OkHttpClient okHttpClient = new OkHttpClient.Builder() .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS) .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS) .addInterceptor(new UrlInterceptor() //這種方式加密是使用loginField的時進行的攔截 .addInterceptor(new LogInterceptor()) .build(); Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) // .addConverterFactory(MyConverterFactory.create()) //loginBody()打開這個 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(baseUrl) .build(); return retrofit; } }
public class UrlInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); //做用:將post中的請求參數取出加密,而且替換原來的請求參數;ps:從新添加的參數是Query形式,並未添加到encode中 //將加密後的data直接使用addEnable請求不成功,可能和後臺的請求類型有關係 HashMap<String, Object> map = new HashMap<>(); //使用@Field添加參數 if ("POST".equals(request.method()) && request.body() instanceof FormBody) {//post請求有參數時 FormBody formBody = (FormBody) request.body(); FormBody.Builder bodyBuilder = new FormBody.Builder();//新建一個請求Body if (formBody.size() > 0) { for (int i = 0; i < formBody.size(); i++) {//將post請求的參數依次取出再加密 map.put(formBody.encodedName(i), formBody.encodedValue(i)); } } request = request.newBuilder() .post(bodyBuilder.build())//請求新的請求參數 .url(request.url() .newBuilder() .addQueryParameter("data", RSAUtils.encrypt(map)) //data是須要的字段 .build()) .build(); } return chain.proceed(request); } }
public class Api { private static ApiService apiService; public static ApiService getApiService() { synchronized (Api.class) { if (apiService == null) { apiService = XApi.getInstance().getRetrofit(BASE_URL).create(ApiService.class); } } return apiService; } } public interface ApiService {//使用loginField()這種方法是爲了在請求數據調用的時候代碼更簡潔,耦合性較低 //登陸 @POST(LOGIN_URL) @FormUrlEncoded Observable<LoginModel> loginField(@Field("phone") String phone, @Field("password") String password); @POST(LOGIN_URL) Observable<LoginModel> loginBody(@Body HashMap<String,String> body); } 如下是使用loginBody()方法請求,因爲@Field的字段註解方式不會調用convert方法,因此纔會在設置OkHttpClient的時候添加自定義Interceptor, 使用Converter: //請求 public class MyRequestConverter<T> implements Converter<T, RequestBody> { private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); private Gson gson; private TypeAdapter<T> adapter; public MyRequestConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public RequestBody convert(T value) throws IOException { value類型和傳入參數有關係 Log.i("hhhh", "request中傳遞的json數據:" + value.toString()); //在此處作加密請求 String postBody = gson.toJson(encrypt(value.toString())); Log.i("hhhh", "轉化後的數據:" + postBody); return RequestBody.create(MEDIA_TYPE, postBody); } } //響應 public class MyResponseConverter<T> implements Converter<ResponseBody, T> { private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); private Gson gson; private TypeAdapter<T> adapter; public MyResponseConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { //此處爲返回數據解密,我這裏沒作解密 JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { return adapter.read(jsonReader); } finally { value.close(); } } } //ConverterFactory,這個是用GsonConverterFactory修改爲本身定義的類 public final class MyConverterFactory<T> extends Converter.Factory { public static MyConverterFactory create() { return create(new Gson()); } @SuppressWarnings("ConstantConditions") // Guarding public API nullability. public static MyConverterFactory create(Gson gson) { if (gson == null) throw new NullPointerException("gson == null"); return new MyConverterFactory(gson); } private final Gson gson; private MyConverterFactory(Gson gson) { this.gson = gson; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new MyResponseConverter<>(gson, adapter); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new MyRequestConverter<>(gson, adapter); } }`