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);
    }
}`
相關文章
相關標籤/搜索