android 网络拦截器统一处理请求参数和返回值加解密实现

前言

项目中遇到参数加密和返回结果加密的业务

这里写一下实现 一来加深记忆 二来为以后参考铺垫

需求

项目在开发中涉及到 登陆 发验证码 认证 等前期准备接口

这些接口需要单独处理 比如不加密 或者有其他的业务需求

剩下的是登陆成功以后的业务需求接口 针对入参和返回值做了RSA AES加密

需求大概是这样 下面看下代码实现逻辑

实现

在网络框架的配置类里添加加密拦截器

java 复制代码
 HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
        OkHttpClient.Builder mOkHttpBuilder = new OkHttpClient.Builder()
                .connectTimeout(CONN_TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .addInterceptor(new EncryptionInterceptor()) //加密拦截器 统一处理

解析

我的业务场景是 前期的 登陆 发验证码 认证 接口不需要做加密

所以我需要在加密拦截器前期做单独处理

java 复制代码
 		 //认证接口不处理加密需求
        if (url.encodedPath().equals("xxx/auth")) {
            return chain.proceed(request);
        }
		
		//登陆和验证码都是get接口所以在这里统一拦截 
        if (method.equals("get") || method.equals("delete")) {
            return chain.proceed(request);
        }

处理完特殊业务场景 就剩统一的post接口 参数统一封装成body

java 复制代码
 		 //请求接口请求参数
        String param = InterceptorUtils.bodyToString(request);

        //获取加密的key
        String aesKey = Hawk.get(AppCode.AES_EKY);
        String encryptData = AESUtils.encrypt(param, aesKey);

        //拿到加密后的json字符串
        String json = new Gson().toJson(new JsonRequest(encryptData));
        RequestBody body = RequestBody.create(request.body().contentType(), json);
        request = request.newBuilder().post(body).build();
        Response response = chain.proceed(request);

下图是加密后的参入 统一用data作为加密key-valuekey用于后端解析

再来看一下返回值解密的代码实现 这里有2个点需要注意一下

对于后端返回的类型 无非是对象Object或者数组Array 2种情况 统一封装

先来看一下返回的加密格式

json 复制代码
 {
    	"code":20000,
    	"data":"N1bBAjZ4m6PGGWJmu53PzSOcyjjUL0Jo3UITcEgmxY
    	    	WcnBZSXKXRK81bS65JVoB8ouAuBLSSQvzVxHAc
    			/pRbdUentgpppoe8wfhKvLuVu9LhVPK9y6I9/rf5nNm4h0+R62ubdUNINLsi6tl+j
				/Gn/gMPAzIoEFtVyQMQvHJ1sH4uh4as0Tnxu51aEknNc8Pm",
    	"errorId":"",
    	"message":"操作成功"
    }

上图中,data是我们的业务返回数据 它可能是Array也可能是Object
encryptData 加密字符串

java 复制代码
	//说明是数组
   if (encryptData != null && encryptData.startsWith("[")) {
            JSONArray jsonArray = JSONArray.parseArray(encryptData);
            decryptObj.setData(jsonArray);
   } else if (encryptData != null && encryptData.startsWith("{")) {
               //说明是对象
            JSONObject jsonObject = JSONObject.parseObject(encryptData);
            decryptObj.setData(jsonObject);
      }

EncryptionInterceptor 实现

java 复制代码
public class EncryptionInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        okhttp3.HttpUrl url = request.url();
        String method = request.method().toLowerCase().trim();

        //认证接口不处理加密需求
        if (url.encodedPath().equals("/isp/app/worker/auth")) {
            return chain.proceed(request);
        }

        if (method.equals("get") || method.equals("delete")) {
            return chain.proceed(request);
        }
        //请求接口请求参数
        String param = InterceptorUtils.bodyToString(request);

        //获取加密的key
        String aesKey = Hawk.get(AppCode.AES_EKY);
        String encryptData = AESUtils.encrypt(param, aesKey);

        //拿到加密后的json字符串
        String json = new Gson().toJson(new JsonRequest(encryptData));
        RequestBody body = RequestBody.create(request.body().contentType(), json);
        request = request.newBuilder().post(body).build();
        Response response = chain.proceed(request);
        return Decrypt(response);
    }


    /**
     * 返回值解密
     * @param response 返回值
     * @return response
     */
    private Response Decrypt(Response response) {
        try {
            Response.Builder builder = response.newBuilder();
            Response clone = builder.build();

            //成功 判断是否等于200
            if (clone.code() != 200) {
                return response;
            }
            ResponseBody body = clone.body();
            if (body != null) {
                MediaType mediaType = body.contentType();
                if (mediaType != null) {
                    if (InterceptorUtils.isText(mediaType)) {
                        String aesKey = Hawk.get(AppCode.AES_EKY);
                        BaseResult result = new 
                        Gson().fromJson(body.string(),BaseResult.class);
                        String encryptData = 
                        AESUtils.decrypt(result.getData().toString(), aesKey);
                        ALog.e("解密返回数据 ->" + encryptData);

                        BaseResult decryptObj = new BaseResult();
                        decryptObj.setCode(result.getCode());
                        decryptObj.setErrorId(result.getErrorId());
                        decryptObj.setMessage(result.getMessage());
                        //说明是数组
                        if (encryptData != null && encryptData.startsWith("[")) {
                            JSONArray jsonArray = JSONArray.parseArray(encryptData);
                            decryptObj.setData(jsonArray);
                        } else if (encryptData != null && encryptData.startsWith("{")) {
                            //说明是对象
                            JSONObject jsonObject = JSONObject.parseObject(encryptData);
                            decryptObj.setData(jsonObject);
                        }
                        String strJson = new Gson().toJson(decryptObj);
                        body = ResponseBody.create(mediaType, strJson);
                        return response.newBuilder().body(body).build();
                    }
                }
            }
        } catch (Exception e) {
            ALog.e("解密错误:" + e.getMessage());
        }

        return response;
    }
}

有什么问题欢迎交流~

相关推荐
fantasy_arch12 分钟前
CPU性能优化-磁盘空间和解析时间
网络·性能优化
带电的小王2 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
是Dream呀2 小时前
Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络
网络·python·神经网络
梦想平凡2 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道3 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
kaixin_learn_qt_ing3 小时前
了解RPC
网络·网络协议·rpc
阿甘知识库3 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
安全小王子3 小时前
Kali操作系统简单介绍
网络·web安全
元争栈道4 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe4 小时前
Android Hook - 动态加载so库
android