rxjava+retrofit請求加解密過程中的坑

學習rxjava和retrofit搭建demo時,用到了公司接口,由於公司的所有網絡請求數據都有進行加密,這給搭建demo的過程中增加了一些困難,這裏將學習以及一些走彎路的過程記錄下來。

1、rxjava+retrofit加解密方案

這裏先簡單介紹一下rxjava+retrofit使用方法


1.1構造服務ApiService



1.2通過retrofit生成ApiService實例


1.3封裝業務方法提供給前臺使用

其中98-112行爲參數的封裝,不同公司有不同的規則,不必過多糾結;

107行爲數據加密,根據自家公司加密方法進行加密;

可以看到定義的ApiService返回爲較原始的ResponseBody,我們不能在頁面上使用api時還進行ResponseBody到所需javaBean的轉換,可能有同學會疑惑這裏爲什麼不直接返回頁面所需的javaBean,道理很簡單,因爲數據加密了,結構與目標javaBean已經完全不同,你如果直接去進行轉換是肯定拿不到你想要的javaBean的,於是想到通過rxjava自身的特點,117行用map操作符將responseBody的string取出後進行解密,然後返回對應泛型的javaBean。

整個加解密的過程比較簡單,中間還是踩了不少坑。



2、過程中遇到的坑


2.1在哪解密?
最開始想到的解密是在OkHttp Interceptor(攔截器)中進行解密。攔截器代碼如下:

public class BaseInterceptor implements Interceptor
{

    private Map<String, String> headers;

    public BaseInterceptor(Map<String, String> headers)
    {
        this.headers = headers;
    }

    @Override
    public Response intercept(Chain chain) throws IOException
    {
        Request.Builder builder = chain.request().newBuilder();
        if (headers != null && headers.size() > 0)
        {
            Set<String> keys = headers.keySet();
            for (String headerKey : keys)
            {
                builder.addHeader(headerKey, headers.get(headerKey)).build();
            }
        }

        Response response = chain.proceed(builder.build());
        return decrypt(response);
    }

    /**
     * 解密過程
     *
     * @param response
     * @return
     * @throws IOException
     */
    private Response decrypt(Response response) throws IOException
    {
        String oldBody = response.body().string();
        Log.i("Interceptor", "oldBody=" + oldBody);
        ServerResponse resp = new Gson().fromJson(oldBody, ServerResponse.class);
        String data = null == resp.getData() ? null : (String) resp.getData();
        String newBody = null;
        if (!TextUtils.isEmpty(data))
        {
            String str = DES3EncryptAndDecrypt.des3DecryptMode(data);
            newBody = oldBody.replace("\"" + data + "\"", str);
        }

        Response res = response.newBuilder().body(ResponseBody.create(null, newBody)).build();
        return res;
    }
}
思路很簡單,就是在37行攔截到response後取出responseBody,然後解密後用明文重新構造一個response返給上層,但是後面發現rxjava會報出一個closed的錯誤,且控制檯沒有任何錯誤信息,在苦苦找不到結果後,QJay大神說response.body().string()會關流,於是進入string()方法看到以下代碼:

明顯finally中關掉了source,導致response根本到不了上層了。
其實上面的問題無非就是body不能獲取到而已,好在HttpLoggingInterceptor裏面有如何獲取到responcebody的方法,這裏就不貼HttpLoggingInterceptor源碼了,內部比較簡單,無非就是根據一些條件打印一些信息而已,這裏只貼出獲取responseBody的代碼,如下:

獲取到responseBody後以爲不會再有什麼問題,將程序跑起來後發現,解密根本沒有成功,雖然原responseBody中的密文已拿到,且已成功解密,但是發現在這裏根本沒有方法來構造response,也就是說不能將攔截到的response中的密文替換問明文,終於這種思路有一個點是始終跨不過的,最後便放棄了這種方案,改爲以上方案解決了解密問題。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章