OkHttp 加密拦截器封装

很多时候,我们都要对request 和response 进行加解密,这时候就需要对Http 重定向,自定义拦截器,将请求和返回值进行拦截,处理后在发送或者解析。下面会分为java 和kotlin 版本。

加密会分为 get 的参数加密 、post 的body 加密,加密的方式大部分都是使用RSA 加密。
直接看代码吧。

java版

public class DataEncryptInterceptor implements Interceptor {
    private static final String TAG = DataEncryptInterceptor.class.getSimpleName();

    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();
        String requestMethod = request.method().toLowerCase().trim();

        HttpUrl url = request.url();


        //协议地址
        String scheme = url.scheme();//  http https
        //域名
        String host = url.host();//   127.0.0.1
        //接口名
        String path = url.encodedPath();//  /test/upload/img

        String key = PrefsUtil.getInstance().getString(Constants.PUBLIC_KEY, "");


      //判断是否需要加密,如果次路径不需要加密,则返回原始request即可
        if (path.isEmpty() || (!path.contains(ApiAddress.CHECK_ROOM_SECRET_OUT) && !path.contains(ApiAddress.CHECK_ENCRYPTION)) || TextUtils.isEmpty(key)) {
            return chain.proceed(request);
        }

        //判断是get 还是post(get 和 delete 是一样的请求方式)
        if (requestMethod.equals("get") || requestMethod.equals("delete")) {
            if (url.encodedQuery() != null) {
                try {
                    String queryparamNames = request.url().encodedQuery();

                   //如果参数是空,则不加密
                    if (queryparamNames == null || TextUtils.isEmpty(queryparamNames)) {

                        //构建新的请求
                        String newUrl = scheme + ":" + host + path;
                        request = request.newBuilder().url(newUrl).build();
                    } else {
                       //对参数进行RSA加密后 ,构建新请求
                        String newParams = RSAUtils.encrypt(queryparamNames, key);

                        //构建新的请求
                        String newUrl = scheme + ":" + host + path + "?" + newParams;
                        request = request.newBuilder().url(newUrl).build();
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    return chain.proceed(request);
                }
            }

        } else {

            //post 请求
            try {
                //获取body 中内容
                RequestBody oldRequestBody = request.body();
                Buffer requestBuffer = new Buffer();
                oldRequestBody.writeTo(requestBuffer);
                String oldBodyStr = requestBuffer.readUtf8();
                
                requestBuffer.close();
                //fromBody 加密
                if (request.body() instanceof FormBody) {


                    //随机AES密钥加密oldBodyStr

                    String encrypt = RSAUtils.encrypt(oldBodyStr, key);

                    Log.e(TAG, "the encrypt is" + encrypt);
                    MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
                    RequestBody newBody = RequestBody.create(mediaType, encrypt);

                    request = request.newBuilder()
                            .header("Content-Type", newBody.contentType().toString())
                            .header("Content-Length", String.valueOf(newBody.contentLength()))
                            .method(request.method(), newBody)
                            .build();
                } else {
                    //生成随机AES密钥并用serverPublicKey进行RSA加密

                    url = request.url();
                    path = url.encodedPath();//
                    String query = url.encodedQuery();//请求参数


                    String encrypt = RSAUtils.encrypt(oldBodyStr, key);
//                    String newQuery = URLEncoder.encode(encrypt, "utf-8");
                    Log.e(TAG, "the encrypt is       " + encrypt);
                    MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
                    //构造新的request

                    HashMap<String, Object> requestParams = DataService.createRequestParams();
                    requestParams.put("body", encrypt);

                    RequestBody requestBody1 = DataService.convertMapToBody(requestParams);

                    RequestBody requestBody = RequestBody.create(mediaType, encrypt);

                    Buffer requestBuffer1 = new Buffer();
                    requestBody1.writeTo(requestBuffer1);
                    String newBodyStr = requestBuffer1.readUtf8();
                    requestBuffer1.close();
                    Log.e(TAG, "the new body is" + newBodyStr);

                    request = request.newBuilder().post(requestBody1).build();
                }

                 //response 拦截判断
                Response response = chain.proceed(request);
                if (response.code() == 200) {//只有约定的返回码才经过加密,才需要走解密的逻辑

                    //用AES密钥解密oldResponseBodyStr
                    ResponseBody oldResponseBody = response.body();
                    String oldResponseBodyStr = oldResponseBody.string();

                    RsaResponse rsaResponse = JSON.parseObject(oldResponseBodyStr, RsaResponse.class);

                    Log.e(TAG, "the response1 is" + rsaResponse.getResponse());
                    if (!TextUtils.isEmpty(rsaResponse.getResponse())){
                        String newResponseBodyStr = RSAUtils.decrypt(rsaResponse.getResponse(), key);
                        Log.e(TAG, "the new response is" + newResponseBodyStr);
                        oldResponseBody.close();
                        //构造新的response
                        MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
                        ResponseBody newResponseBody = ResponseBody.create(mediaType, newResponseBodyStr);

                        response = response.newBuilder().body(newResponseBody).build();
                    }

                }
//                response.close();
                //返回
                return response;


            } catch (Exception e) {
                e.printStackTrace();

                return chain.proceed(request);
            }
        }

        return chain.proceed(chain.request());
    }
}

kotlin 版



class DataEncryptInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        val newBuilder = request.newBuilder()

        val requestMethod = request.method().lowercase(Locale.getDefault()).trim { it <= ' ' }
        var url = request.url()
        val scheme = url.scheme() //  http https
        val host = url.host() //   127.0.0.1
        var path = url.encodedPath() //  /test/upload/img

        //判断是get 还是post
        if (requestMethod == "get" || requestMethod == "delete") {
            if (url.encodedQuery() != null) {
            }
        } else {
            return try {
                val oldRequestBody = request.body()
                val requestBuffer = Buffer()
                oldRequestBody!!.writeTo(requestBuffer)
                val oldBodyStr = requestBuffer.readUtf8()
                requestBuffer.close()
                if (request.body() is FormBody) {


                    //随机AES密钥加密oldBodyStr
                    val encrypt: String = RSAUtils.encrypt(oldBodyStr, key)
                    val mediaType = MediaType.parse("text/plain; charset=utf-8")
                    val newBody = RequestBody.create(mediaType, encrypt)
                    request = request.newBuilder()
                        .header("Content-Type", newBody.contentType().toString())
                        .header("Content-Length", newBody.contentLength().toString())
                        .method(request.method(), newBody)
                        .build()
                } else {
                    //生成随机AES密钥并用serverPublicKey进行RSA加密
                    url = request.url()
                    path = url.encodedPath() //
                    val query = url.encodedQuery() //请求参数
                    val encrypt: String = RSAUtils.encrypt(oldBodyStr, key)
                    //                    String newQuery = URLEncoder.encode(encrypt, "utf-8");
                    Log.e(DataEncryptInterceptor.TAG, "the encrypt is       $encrypt")
                    val mediaType = MediaType.parse("application/json; charset=utf-8")
                    //构造新的request
                    val requestParams: HashMap<String, Any> = DataService.createRequestParams()
                    requestParams["body"] = encrypt
                    val requestBody1: RequestBody = DataService.convertMapToBody(requestParams)
                    val requestBody = RequestBody.create(mediaType, encrypt)
                    val requestBuffer1 = Buffer()
                    requestBody1.writeTo(requestBuffer1)
                    val newBodyStr = requestBuffer1.readUtf8()
                    requestBuffer1.close()
                    request = request.newBuilder().post(requestBody1).build()
                }
                var response = chain.proceed(request)
                if (response.code() == 200) { //只有约定的返回码才经过加密,才需要走解密的逻辑

                    //用AES密钥解密oldResponseBodyStr
                    val oldResponseBody = response.body()
                    val oldResponseBodyStr = oldResponseBody!!.string()
                    val rsaResponse: RsaResponse =
                        JSON.parseObject(oldResponseBodyStr, RsaResponse::class.java)
                 
                    if (!TextUtils.isEmpty(rsaResponse.getResponse())) {
                        val newResponseBodyStr: String =
                            RSAUtils.decrypt(rsaResponse.getResponse(), key)
                        oldResponseBody!!.close()
                        //构造新的response
                        val mediaType = MediaType.parse("text/plain; charset=utf-8")
                        val newResponseBody = ResponseBody.create(mediaType, newResponseBodyStr)
                        response = response.newBuilder().body(newResponseBody).build()
                    }
                }
                //                response.close();
                //返回
                response
            } catch (e: Exception) {
                e.printStackTrace()
                chain.proceed(request)
            }
        }

        return chain.proceed(chain.request())
    }
}

RSAUtils

package com.oculus.rayvision.cloudxr.ovr.utils;

import android.nfc.Tag;

import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import org.json.JSONArray;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class RSAUtils {


    public static final String rsa = "公钥";
    /**
     * 密钥长度 于原文长度对应 以及越长速度越慢
     */
    private final static int KEY_SIZE = 1024;
    private static final String TAG = RSAUtils.class.getSimpleName();

    /**
     * RSA公钥加密
     *
     * @param str       加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        //base64编码的公钥


        Log.e(TAG, "the str is" + str);
        Log.e(TAG, "the publick key is" + publicKey);
        byte[] decoded = Base64.getMimeDecoder().decode(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
//        Cipher cipher = Cipher.getInstance("RSA");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] bytes = cipher.doFinal(str.getBytes());
//        String res = new String(bytes);
        Log.e(TAG, "s" + Base64.getEncoder().encodeToString(bytes));
        String s = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
        Log.e(TAG, "ss=" + s);

        return s;
    }


    /**
     * RSA公钥解密
     *
     * @param text          加密字符串
     * @param publicKeyText 私钥
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String text, String publicKeyText) {
        if (TextUtils.isEmpty(text)) {
            return "";
        }
        String value = "";
        try {
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(publicKeyText));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] decode = Base64.getMimeDecoder().decode(text);
            byte[] result = cipher.doFinal(decode);
            value = new String(result);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return value;
    }
    public static String decryptOld(String str, String privateKey) {
        //64位解码加密后的字符串
        String outStr = null;
        try {

//
            byte[] inputByte = Base64.getDecoder().decode(str);
            //base64编码的私钥

            byte[] decoded = Base64.getDecoder().decode(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            outStr = new String(cipher.doFinal(inputByte), StandardCharsets.UTF_8);



        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "decypt exception is" + e.getMessage());
        }
        return outStr;
    }


    public static String baseConvertStr(String str) {
        if (null != str) {
            Base64.Decoder decoder = Base64.getDecoder();
            try {
                String gbk = new String(decoder.decode(str.getBytes()), "GBK");
                Log.e(TAG, "the gbk is " + gbk);
                gbk = gbk.replaceAll("-----BEGIN PUBLIC KEY-----", "");
                gbk = gbk.replaceAll("-----END PUBLIC KEY-----", "");
                return gbk;
            } catch (UnsupportedEncodingException e) {
                return null;
            }
        }
        return null;
    }


}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值