okhttp3.x+retrofit2.x post请求加密(一)

okhttp3.x+retrofit2.x post请求加密 (单一类型参数 使用@Field)json

  • 主要原理是在请求发送以前作一个拦截操做,将原来的post请所带的参数进行加密后,再从新发送,因为为了解耦和代码的简洁性,请求的时的参数选用的时@Field注解
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);
    }
}`
相关文章
相关标签/搜索