OkHttp-拦截器的非常规操作,查漏补缺

public class TestInterceptor implements Interceptor {
private String newHost = “127.0.0.1”;
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();
//http://127.0.0.1/test/upload/img?userName=xiaoming&userPassword=12345
String scheme = url.scheme();// http https
String host = url.host();// 127.0.0.1
String path = url.encodedPath();// /test/upload/img
String query = url.encodedQuery();// userName=xiaoming&userPassword=12345

StringBuffer sb = new StringBuffer();
String newUrl = sb.append(scheme).append(newHost).append(path).append(“?”).append(query).toString();

Request.Builder builder = request.newBuilder()
.url(newUrl);

return chain.proceed(builder.build());
}
}

上面只是简单的换了一下host retrofit可以轻易做到,在构造retrofit的时候可以修改baseUrl,但是如果要换path呢,这时候可能retrofit不是那么好做,而且你需要每个地方都要换,这时候你可以在这里当成一个统一的入口new一个新的path即可。简单吧,对于后面的每个字段说明意思我在后面也有备注,可以看到拆分后的样子

#请求体数据加密
既然要对请求体加密,那肯定要知道请求体在哪里,然后才能加密,其实都一样不论是加密url里面的query内容还是加密body体里面的都一样,只要拿到了对应的数据我们想怎么做怎么,有的接口比较奇葩,他需要根据请求体的内容进行签名认证。不论如何我们拿到了请求体当然想怎么样就怎么样,看下嘛的操作

  • 加密query内容

public class TestInterceptor implements Interceptor {
private String newHost = “127.0.0.1”;

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();

//http://127.0.0.1/test/upload/img?userName=xiaoming&userPassword=12345
String scheme = url.scheme();// http https
String host = url.host();// 127.0.0.1
String path = url.encodedPath();// /test/upload/img
String query = url.encodedQuery();// userName=xiaoming&userPassword=12345

StringBuffer sb = new StringBuffer();
sb.append(scheme).append(newHost).append(path).append(“?”);
Set queryList = url.queryParameterNames();
Iterator iterator = queryList.iterator();

for (int i = 0; i < queryList.size(); i++) {

String queryName = iterator.next();
sb.append(queryName).append(“=”);
String queryKey = url.queryParameter(queryName);
//对query的key进行加密
sb.append(CommonUtils.getMD5(queryKey));
if (iterator.hasNext()) {
sb.append(“&”);
}
}

String newUrl = sb.toString();

Request.Builder builder = request.newBuilder()
.url(newUrl);

return chain.proceed(builder.build());
}
}

这样拼接的query内容就可以直接统一加密了。我这里只是简单的md5加密 如果说服务端和客户端定义了一套加密解密协议,就可以在这里进行特定的加密方式进行加密

  • 加密body体内容

public class TestInterceptor implements Interceptor {
private String newHost = “127.0.0.1”;

public static String requestBodyToString(RequestBody requestBody) throws IOException {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
return buffer.readUtf8();
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();

//http://127.0.0.1/test/upload/img?userName=xiaoming&userPassword=12345
String scheme = url.scheme();// http https
String host = url.host();// 127.0.0.1
String path = url.encodedPath();// /test/upload/img
String query = url.encodedQuery();// userName=xiaoming&userPassword=12345

StringBuffer sb = new StringBuffer();
sb.append(scheme).append(newHost).append(path).append(“?”);
Set queryList = url.queryParameterNames();
Iterator iterator = queryList.iterator();

for (int i = 0; i < queryList.size(); i++) {

String queryName = iterator.next();
sb.append(queryName).append(“=”);
String queryKey = url.queryParameter(queryName);
//对query的key进行加密
sb.append(CommonUtils.getMD5(queryKey));
if (iterator.hasNext()) {
sb.append(“&”);
}
}

String newUrl = sb.toString();

RequestBody body = request.body();
String bodyToString = requestBodyToString(body);
TestBean testBean = GsonTools.changeGsonToBean(bodyToString, TestBean.class);
String userPassword = testBean.getUserPassword();
//加密body体中的用户密码
testBean.setUserPassword(CommonUtils.getMD5(userPassword));

String testGsonString = GsonTools.createGsonString(testBean);
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json”), testGsonString);

Request.Builder builder = request.newBuilder()
.post(requestBody)
.url(newUrl);

return chain.proceed(builder.build());
}
}

从上面可以看出我们先拿到body体的内容然后解析后,拿到对应的实体类,然后进行加密,再次创建一个新的body体里面然后post过去,即可达到body体加密,我这只是一种body加密方法,也有可能是拿到body然后进行加密然后对加密后的东西加入head 当成签名使用。
最终这种拦截器方式的加密也是一种统一代码入口的方式。

#HEAD动态添加
在日常的开发中,可能每个接口对应的header不同有的多有的少。不可能说每个接口都写一个拦截器进行添加头部。这时候我们可以换个思维来考虑这个问题。怎么做呢,其实也是为了统一代码,同一种操作不要再多个地方进行,这样修改起来很麻烦。统一入口,统一出口。

public class TestInterceptor implements Interceptor {
private String newHost = “127.0.0.1”;
private String path1 = “/test/upload/img”;
private String path2 = “/test/upload/voice”;

public static String requestBodyToString(RequestBody requestBody) throws IOException {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
return buffer.readUtf8();
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();

//http://127.0.0.1/test/upload/img?userName=xiaoming&userPassword=12345
String scheme = url.scheme();// http https
String host = url.host();// 127.0.0.1
String path = url.encodedPath();// /test/upload/img
String query = url.encodedQuery();// userName=xiaoming&userPassword=12345

StringBuffer sb = new StringBuffer();
sb.append(scheme).append(newHost).append(path).append(“?”);
Set queryList = url.queryParameterNames();
Iterator iterator = queryList.iterator();

for (int i = 0; i < queryList.size(); i++) {

String queryName = iterator.next();
sb.append(queryName).append(“=”);
String queryKey = url.queryParameter(queryName);
//对query的key进行加密
sb.append(CommonUtils.getMD5(queryKey));
if (iterator.hasNext()) {
sb.append(“&”);
}
}

String newUrl = sb.toString();

RequestBody body = request.body();
String bodyToString = requestBodyToString(body);
TestBean testBean = GsonTools.changeGsonToBean(bodyToString, TestBean.class);
String userPassword = testBean.getUserPassword();
//加密body体中的用户密码
testBean.setUserPassword(CommonUtils.getMD5(userPassword));

String testGsonString = GsonTools.createGsonString(testBean);
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json”), testGsonString);

Request.Builder builder = request.newBuilder()
.post(requestBody)
.url(newUrl);

switch (path) {
case path1:
builder.addHeader(“token”,“token”);
break;
case path2:
builder.addHeader(“token”,“token”);
builder.addHeader(“uid”,“uid”);
break;
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

[外链图片转存中…(img-sr96eTsN-1712788780443)]

[外链图片转存中…(img-KXDYEBDG-1712788780443)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值