前两天因为短信验证码接口被人恶意调用,狂刷验证码账户里的钱,所以做了一次数据加密。网络请求使用的是Retrofit,解析工厂用的是GsonConverterFactory,依赖的是
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
<一>解密部分
本来是打算加密整个messagebody的就是直接过来的消息体就是整个未解析的json串来加密的,但是后来因为ios这边有点问题就不对整个串加密了,在外边包裹一层基本形式就是这样了
{"data":"加密后的json串"}
解密之前需要把这个串给先解析,之后对dada中的数据解密就可以了,接口的大致情况后,设计Retrofit如何解密,就是在数据请求回来解析Json串把数据获取到,解密出来分发下午就可以了。值钱我用的是GsonConverterFactory这个是,依赖的一个库没法修改我们就仿照他的自己写一个。先贴一下GsonConverterFactory,不然大家看了不知道是啥如何做修改。
/**
* A {@linkplain Converter.Factory converter} which uses Gson for JSON.
* <p>
* Because Gson is so flexible in the types it supports, this converter assumes that it can handle
* all types. If you are mixing JSON serialization with something else (such as protocol buffers),
* you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this instance}
* last to allow the other converters a chance to see their types.
*/
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
很简单继承自Converter.Factory,实现了重写了两个方法,requestBodyConverter, responseBodyConverter,一个是请求是的处理,另外一个是响应的梳理,机密一般都responseBodyConverter里面处理,看一下返回的数据GsonResponseBodyConverter<>(gson, adapter);
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
GsonResponseBodyConverter里的代码
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(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();
}
}
}
就是讲ResponseBody 给予,解析出来。很简单我们就仿照这个改写一下 return adapter.read(jsonReader);数据之前先将ResponseBody 使用Gson解析一下,取出data中的数据,再讲数据解密,再传给adapter去处理就可以了。下面是我写的JsonConverterFactory
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
/**
* Created by Administrator on 2017/8/10 0010.
*/
public class JsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static JsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static JsonConverterFactory create(Gson gson) {
return new JsonConverterFactory(gson);
}
private final Gson gson;
private JsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new JsonResponseBodyConverter<>(gson, adapter); //响应
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new JsonRequestBodyConverter<>(gson, adapter); //请求
}
}
看一下JsonRequestBodyConverter<>(gson, adapter)里面的代码:
*/
public class JsonResponseBodyConverter <T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
JsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
String response = value.string();
Logger.e("retrofitResponse==========", response.toString());
AllResponseData allResponseData = gson.fromJson(response, AllResponseData.class);
//获取加密数据,解密,之后再让adapter去处理json串,解析具体的数据就可以了
try{
return adapter.fromJson(DesUtil.decrypt(allResponseData.getDesData(),DesUtil.MYSELFKEY));
} catch (Exception e) {
e.printStackTrace();
} finally {
value.close();
}
return null;
}
}
<二>加密部分
加密的话就在JsonRequestBodyConverter里面处理
package com.house_pattern.utils;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;
/**
* Created by Administrator on 2017/8/10 0010.
*/
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
在这里面将数据拦截处理了做创建一个RequestBody返回就可以了。