Android中对接口进行统一加密

在之前的博客中我们介绍了 加密方案的选择Android中加解密需要注意的地方

本篇博客我们主要来看一下Android结合Retrofit进行加解密时的注意事项。

在开发过程中,接口是很多的,我们不可能分别对每个接口的请求数据都进行加密,这样写起来以及后期维护是非常麻烦的,所以,肯定要是统一处理的
还有我们常用的GetPostDeletePut请求他们的请求数据存放位置是不一样的,所以,我们需要对不同的请求方式做处理。
上传文件时,一般是不需要加密的,还有通过Retrofit请求第三方接口时也是不需要加密的,这些我们都需要考虑到。

目前来讲,我们最常使用的网络请求框架就是Retrofit了,Retrofit实际上就是对OkHttp的封装,网上的一些博客对加解密的处理是在转换器中处理的,实际上我认为这种方式并不好,首先我们来看一下GsonConverterFactory的源码.

看过源码你会发现,转换器只能对响应体和请求体进行处理,解密的时候还好说,加密的时候如果你使用的是Get或者Delete这中请求方式时,转换器是不好进行处理的。所以,关于Retrofit的统一加解密还是建议在拦截器中进行处理。

下面我们来总结一下注意事项:

  • 加解密要统一进行处理,方便维护
  • 加密时要对不同的加密方式进行不同的加密处理
  • 第三方接口,不加密
  • 上传时不加密

Retrofit 统一加密拦截器

拦截器对请求数据加密流程

  1. 获取请求的数据
  2. 对请求数据进行加密
  3. 根据不同的请求方式构造新的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()

然后就可以和后台进行联调测试了。


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

更多相关文章

  1. android 蓝牙ble app开发(二) -- 关键概念,连接参数,连接请求
  2. android 蓝牙ble app开发(二) -- 关键概念,连接参数,连接请求
  3. 曝Android机冷冻后变"傻" 加密数据随意访问
  4. Android(安卓)So简单加固
  5. 使用Struts2服务端与android交互
  6. Android(安卓)MD5加密算法
  7. android RSA和Java RSA加密不一致的坑
  8. android开源框架源码分析:Okhttp
  9. android应用安全——数据安全

随机推荐

  1. Android(安卓)RabbitMQ使用之RabbitMQ安
  2. 安卓(android)使用GPS,获取经纬度
  3. Titanium 使用刘明星的Jpush module做and
  4. android adb工具
  5. Android中的常用的对话框
  6. Android(安卓)Studio 3.0开始android Dev
  7. android插件汇总
  8. Android修改字体样式
  9. Android(安卓)设置EditText光标Curso颜色
  10. APIDEMO PREFERENCE 学习 ACTIVTIY