retrofit给参数统一加密

网络请求中难免对所有请求添加公共参数,或者对参数进行加密,在使用OkHttp的时候可以封装常用GET和POST等请求的公共方法,拿到参数进行公共参数的添加或者参数的加密,那么使用retrofit呢?我们都知道retrofit直接走注解的,那么怎么处理,封装一个对参数进行处理的公用方法,每次请求前都调用吗?其实有更优雅的方法,那就是使用OkHttp的Interceptor

Interceptor

1
2
3
4
5
6
7
8
9
10
11
public interface Interceptor {
Response intercept(Chain chain) throws IOException;

interface Chain {
Request request();

Response proceed(Request request) throws IOException;

@Nullable Connection connection();
}
}

其中chain可以获取到原请求,接下来主要注意下面代码中如何取出GET和POST方法中原请求参数值,并且修改或者添加值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Interceptor mInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {

Request request = chain.request();
String method = request.method();

//用于存储原请求的参数
HashMap<String, String> params = new HashMap<>();

//get方法和post方法处理参数情况不一样,需要区分开来
if("GET".equals(method)){
HttpUrl url = request.url();
for (int i = 0; i < url.querySize(); i++) {

//取出url中?后的参数
String key = url.queryParameterName(i);
String value = url.queryParameterValue(i);

params.put(key,value);
//可以修改内容,例如给key为phone或者password的值进行RSA加密
RSAUtils.xxx(params);
}


HttpUrl.Builder newBuilder = url.newBuilder();

for (Map.Entry<String, String> entry : params.entrySet()) {
newBuilder.addQueryParameter(entry.getKey(), entry.getValue());
}

//添加公共参数可以单独这样写 也可以直接在上面的map中先添加再遍历map添加

newBuilder.addEncodedQueryParameter("key1","value1")
.addEncodedQueryParameter("key2","value2")
.build();

//构建新的request
request = request.newBuilder()
.url(newBuilder.build()).build();


}else if("POST".equals(method)){

//这里是表单请求(postJson形式后面讲)
if (request.body() instanceof FormBody) {
FormBody.Builder builder = new FormBody.Builder();
FormBody oldFormBody = (FormBody) request.body();
for (int i=0;i<oldFormBody.size();i++){
//取出并保存原请求参数
params.put(oldFormBody.encodedName(i), oldFormBody.encodedValue(i));
}

//对参数进行加密,对原parms进行了处理
RSAUtils.xxx(params);

//添加加密后的参数
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
//构建新的request
request = request.newBuilder()
.post(builder.build()).build();
}

}

return chain.proceed(request);
}
};

那么retrofit如何进行postJson形式的请求呢?实际上可以直接使用post同时修改上面最后部分代码

请求的时候还是按照普通post表单提交请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
else if(method.equals("POST")) {
if (original.body() instanceof RequestBody) {
RequestBody requestBody = original.body(); //获取请求体
Buffer buffer = new Buffer(); //创建缓存
requestBody.writeTo(buffer); //把请求体的内容写入缓存
//读取原请求的参数,String类型
String paramsStr = buffer.readUtf8();
Gson gson = new GsonBuilder().disableHtmlEscaping().create();

//转成map
Map<String, String> map = gson.fromJson(paramsStr, new TypeToken<Map<String, String>>() {}.getType());


//对参数进行处理 添加共参,加密等
RSAUtils.xxx(params);

RequestBody newsRequestBody = RequestBody.create(MediaType.parse("application/json; charset=UTF-8"), gson.toString(map));
//构建新的请求
request = builder.post(newsRequestBody).build();
}

下面是post表单提交请求的方法使用

1
2
3
4
/** 检查版本更新 **/
@FormUrlEncoded
@POST("app/version/findNewVersion")
Observable<BaseRespose<VersionBean>> checkUpdate(@FieldMap ArrayMap<String,String> params);

下面是postJson请求的方法使用

1
2
3
/** 检查版本更新 **/
@POST("app/version/findNewVersion")
Observable<BaseRespose<VersionBean>> checkUpdate(@Body ArrayMap<String,String> params);

Interceptor的使用是在OkHttpClient初始化的时候添加

1
2
3
4
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.addInterceptor(mInterceptor)
....
.build();