Android结合Retrofit实现统一加解密处理(Get、Post、Delete、Put)
Android中对接口进行统一加密
在之前的博客中我们介绍了 加密方案的选择 和 Android中加解密需要注意的地方
本篇博客我们主要来看一下Android结合Retrofit进行加解密时的注意事项。
在开发过程中,接口是很多的,我们不可能分别对每个接口的请求数据都进行加密,这样写起来以及后期维护是非常麻烦的,所以,肯定要是统一处理的
还有我们常用的Get、Post、Delete、Put请求他们的请求数据存放位置是不一样的,所以,我们需要对不同的请求方式做处理。
上传文件时,一般是不需要加密的,还有通过Retrofit请求第三方接口时也是不需要加密的,这些我们都需要考虑到。
目前来讲,我们最常使用的网络请求框架就是Retrofit了,Retrofit实际上就是对OkHttp的封装,网上的一些博客对加解密的处理是在转换器中处理的,实际上我认为这种方式并不好,首先我们来看一下GsonConverterFactory的源码.
看过源码你会发现,转换器只能对响应体和请求体进行处理,解密的时候还好说,加密的时候如果你使用的是Get或者Delete这中请求方式时,转换器是不好进行处理的。所以,关于Retrofit的统一加解密还是建议在拦截器中进行处理。
下面我们来总结一下注意事项:
- 加解密要统一进行处理,方便维护
- 加密时要对不同的加密方式进行不同的加密处理
- 第三方接口,不加密
- 上传时不加密
Retrofit 统一加密拦截器
拦截器对请求数据加密流程
- 获取请求的数据
- 对请求数据进行加密
- 根据不同的请求方式构造新的request
由于加密的相关逻辑需要跟后台商量,下面代码主要是看实现逻辑和注意事项,具体加密方法根据自身情况进行修改。
加密方案的选择可以看博客开始给的连接去选择。
/** * @description: 对请求数据进行加密处理 * @author : yzq * @date : 2019/3/16 * @time : 16:37 * */class RequestEncryptInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() var charset = Charset.forName("UTF-8") val method = request.method().toLowerCase().trim() val url = request.url() /*本次请求的接口地址*/ val apiPath = "${url.scheme()}://${url.host()}:${url.port()}${url.encodedPath()}".trim() /*服务端的接口地址*/ val serverPath = "${url.scheme()}://${url.host()}/".trim() /*如果请求的不是服务端的接口,不加密*/ if (!serverPath.startsWith(ServerConstants.getServerUrl())) { return chain.proceed(request) } /*如果请求方式是Get或者Delete,此时请求数据是拼接在请求地址后面的*/ if (method.equals("get") || method.equals("delete")) { /*如果有请求数据 则加密*/ if (url.encodedQuery() != null) { try { val queryparamNames = request.url().encodedQuery() val encryptqueryparamNames=“这里调用加密的方法,自行修改” //拼接加密后的url,参数字段自己跟后台商量,这里我用param,后台拿到数据先对param进行解密,解密后的数据就是请求的数据 val newUrl = "$apiPath?param=$encryptqueryparamNames" //构建新的请求 request = request.newBuilder().url(newUrl ).build() } catch (e: Exception) { e.printStackTrace() return chain.proceed(request) } } } else { //不是Get和Delete请求时,则请求数据在请求体中 val requestBody = request.body() /*判断请求体是否为空 不为空则执行以下操作*/ if (requestBody != null) { val contentType = requestBody.contentType() if (contentType != null) { charset = contentType.charset(charset) /*如果是二进制上传 则不进行加密*/ if (contentType.type().toLowerCase().equals("multipart")) { return chain.proceed(request) } } /*获取请求的数据*/ try { val buffer = Buffer() requestBody.writeTo(buffer) val requestData = URLDecoder.decode(buffer.readString(charset).trim(), "utf-8") val encryptData=“这里调用加密的方法,自行修改” /*构建新的请求体*/ val newRequestBody = RequestBody.create(contentType, encryptData) /*构建新的requestBuilder*/ val newRequestBuilder = request.newBuilder() //根据请求方式构建相应的请求 when (method) { "post" -> newRequestBuilder.post(newRequestBody) "put" -> newRequestBuilder.put(newRequestBody) } request = newRequestBuilder.build() } catch (e: Exception) { LogUtils.e("加密异常====》${e}") return chain.proceed(request) } } } return chain.proceed(request) }}
好了,加密拦截器基本就是这样
Retrofit 统一解密拦截器
解密就简单跟多了,直接处理相应体即可,下面是参考代码
/** * @description: 对响应数据进行解密 * @author : yzq * @date : 2019/3/20 * @time : 16:13 * */class ResponseDecryptInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() var response = chain.proceed(request) if (response.isSuccessful) { val responseBody = response.body() if (esponseBody != null) { /*开始解密*/ try { val source = responseBody.source() source.request(java.lang.Long.MAX_VALUE) val buffer = source.buffer() var charset = Charset.forName("UTF-8") val contentType = responseBody.contentType() if (contentType != null) { charset = contentType.charset(charset) } val bodyString = buffer.clone().readString(charset) val responseData = “这里调解密的方法” /*将解密后的明文返回*/ val newResponseBody = ResponseBody.create(contentType, responseData.trim()) response = response.newBuilder().body(newResponseBody).build() } catch (e: Exception) { /*异常说明解密失败 信息被篡改 直接返回即可 */ LogUtils.e("解密异常====》${e}") return response } } else { LogUtils.i("响应体为空") } } return response }}
好了,解密拦截器就完成了。
加解密拦截器写好之后添加到okHttp中即可。
val okHttpBuilder = OkHttpClient.Builder() .addInterceptor(RequestHeadersInterceptor()) .addInterceptor(RequestEncryptInterceptor()) .addInterceptor(initLogInterceptor()) .addInterceptor(ResponseDecryptInterceptor()) .build()
然后就可以和后台进行联调测试了。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
更多相关文章
- Android Studio 基础 之 一键快速实现一个类的 构造函数、getter
- Android Studio酷炫插件(一)——自动化快速实现Parcelable接口序列
- Android中的UID和PID意义,及查看方式
- Android绘图机制(三)——自定义View的实现方式以及半弧圆新控件
- 曝Android机冷冻后变"傻" 加密数据随意访问