Retrofit 之加密和解密

Retrofit 是基于OKHttp的一个Restful的http请求框架,在Android的网络请求库中,Retrofit是最为热门的一个,而且,Retrofit本来就是Java写的,所以在普通的Java项目中也可以使用。比起使用jdk的接口要方便的多。

网上关于Retrofit的使用教程也很多,如果对于基本的使用还不是很熟悉的话,可以先去看下基本的使用教程。今天要讲的是Retrofit的加密和解密。在项目中遇到一个需求,就是在发送网络请求之前,需要把数据进行加密,在收到相应的时候,需要把相应的数据解密,这个是非常常见的一个场景。比如,我有一个接口是这么定义的:

 @POST("partners")
 Call addPartner(@Body Partner partner);

就是使用POST方法,body是一个Partner对象。而且要求需要加密整个Partner,加密后是一个字符串(对于其他的类型,请根据需要自行调整)。

那么在使用Retrofit的时候如何实现呢?下面介绍两种方法:

一、修改接口,在传入参数前加密

先把Body类型改成String,如下:

 @POST("partners")
 Call addPartner(@Body String decodePartnerStr);

然后,将整个partner加密成字符串后,进行传输。这样就可以实现。
但是,但是,这么做,首先,需要有权限改接口的定义;其次,如果加密方式都一样,而且接口非常多,那么每次调用接口前都需要手动进行加密,一个是很麻烦(重复的事情交给计算机),一个是扩展性很差(万一以后加密方式改了呢?)。是不是?那么可不可以通过Retrofit解决呢?答案是肯定的,接着往下看。

二、使用 Retrofit.Builder 的 addConverterFactory 方法

根据方法名你肯定已经猜到了这个方法的作用。没错,就是增加Converter 对传输信息进行 Convert的。
我们看下这个方法的定义:

public Retrofit.Builder addConverterFactory(retrofit2.Converter.Factory factory) {
            this.converterFactories.add(Utils.checkNotNull(factory, "factory == null"));
            return this;
}

看一下retrofit2.Converter.Factory 的定义:

public interface Converter {
    T convert(F var1) throws IOException;

    public abstract static class Factory {
        public Factory() {
        }

        public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }

        public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return null;
        }

        public Converter stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }
    }
}

它是一个static的抽象类,返回的就是一个Converter对象。所以,我们需要创建一个继承它的Factory实现类,实现我们需要的方法,如果在发送请求之前做转换,则实现 requestBodyConverter方法,如果需要对相应体进行转换,则需要实现responseBodyConverter 。 记得么,我们需要加密请求体,解密相应体。

下面开始。
创建进行加密操作的Converter 类 EncodeRequestBodyConverter:
Base64Utils.encode(adapter.toJson(o))就是对对象o进行base64加密,根据需要替换即可。

static class EncodeRequestBodyConverter implements Converter {
        private Gson gson;
        private TypeAdapter adapter;

        public EncodeRequestBodyConverter(T p0, TypeAdapter adapter) {
            this.adapter = adapter;
        }

        public EncodeRequestBodyConverter(Gson gson, TypeAdapter adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override
        public RequestBody convert(T o) throws IOException {
            return RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), Base64Utils.encode(adapter.toJson(o)));
        }
    }

创建进行解密操作的Converter 类 DecodeRequestBodyConverter:
Base64Utils.decode(responseBody.string())就是对response执行base64解密,根据需要进行替换即可。

static class DecodeResponseBodyConverter implements Converter {
        private TypeAdapter adapter;
        private Gson gson;

        public DecodeResponseBodyConverter(TypeAdapter adapter) {
            this.adapter = adapter;
        }

        public DecodeResponseBodyConverter(Gson gson, TypeAdapter adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override
        public T convert(ResponseBody responseBody) throws IOException {
            return adapter.fromJson(Base64Utils.decode(responseBody.string()));
        }
    }

创建Converter.Factory的实现类:

static final class ConverterFactory extends Converter.Factory {
        public static ConverterFactory create() {
            return create(new Gson());
        }

        private static ConverterFactory create(Gson gson) {
            return new ConverterFactory(gson);
        }

        private final Gson gson;

        private ConverterFactory(Gson gson) {
            if (gson == null) throw new NullPointerException("gson == null");
            this.gson = gson;
        }

        @Override
        public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
            return new DecodeResponseBodyConverter<>(adapter);
        }

        @Override
        public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
            return new EncodeRequestBodyConverter(gson, adapter);
        }


    }

这些需要的类定义好了之后,怎么调用呢?就是用你创建的Retrofit的实例调用即可:

builder.addConverterFactory(ConverterFactory.create(new Gson()));

赶快去试试吧。
需要监控Retrofit的每次调用?请看Retrofit 之日志。

你可能感兴趣的:(Retrofit 之加密和解密)