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;
    }
}

有什么问题欢迎交流~

相关推荐
程序员陆业聪25 分钟前
Android 平台 AI Agent 技术架构深度解析
android·人工智能
DianSan_ERP5 小时前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
BD_Marathon6 小时前
工厂方法模式
android·java·工厂方法模式
呉師傅6 小时前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑
王码码20356 小时前
Flutter for OpenHarmony:socket_io_client 实时通信的事实标准(Node.js 后端的最佳拍档) 深度解析与鸿蒙适配指南
android·flutter·ui·华为·node.js·harmonyos
勇气要爆发7 小时前
吴恩达《LangChain LLM 应用开发精读笔记》2-Models, Prompts and Parsers 模型、提示和解析器
android·笔记·langchain
Railshiqian7 小时前
给android源码下的模拟器添加两个后排屏的修改
android·开发语言·javascript
2501_946205528 小时前
晶圆机器人双臂怎么选型?适配2-12寸晶圆的末端效应器有哪些?
服务器·网络·机器人
linux kernel8 小时前
第七部分:高级IO
服务器·网络
数字护盾(和中)8 小时前
BAS+ATT&CK:企业主动防御的黄金组合
服务器·网络·数据库