1. 程式人生 > >android js呼叫java 4.2之下漏洞的解決方案

android js呼叫java 4.2之下漏洞的解決方案

在反射呼叫的時候把當前物件傳入,就可以呼叫成員方法了,這樣的話整個架構就比較靈活,感謝safe-java-js-webview-bridge的作者提供了這麼好的解決方案!
<span style="font-size:14px;">public String call(WebView webView, String jsonStr) {
        if (!TextUtils.isEmpty(jsonStr)) {
            try {
                JSONObject callJson = new JSONObject(jsonStr);
                String methodName = callJson.getString("method");
                JSONArray argsTypes = callJson.getJSONArray("types");
                JSONArray argsVals = callJson.getJSONArray("args");
                //Log.e("print",methodName+"="+argsTypes+"="+argsVals);

                String sign = methodName;
                int len = argsTypes.length();
                Object[] values = new Object[len];
                int numIndex = 0;
                String currType;
                for (int k = 0; k < len; k++) {
                    currType = argsTypes.optString(k);
                    if ("string".equals(currType)) {
                        sign += "_S";
                        values[k] = argsVals.isNull(k) ? null : argsVals.getString(k);
                    } else if ("number".equals(currType)) {
                        sign += "_N";
                        //為了標記for迴圈的判斷 如果第一位就是number型別排除0
                        numIndex = numIndex * 10 + k + 1;
                        Log.e("print", "numIndex:" + numIndex);
                    } else if ("boolean".equals(currType)) {
                        sign += "_B";
                        values[k] = argsVals.getBoolean(k);
                    } else if ("object".equals(currType)) {
                        sign += "_O";
                        values[k] = argsVals.isNull(k) ? null : argsVals.getJSONObject(k);
                    } else if ("function".equals(currType)) {
                        sign += "_F";
                        values[k] = new JsCallback(webView, mInjectedName, argsVals.getInt(k));
                    } else {
                        sign += "_P";
                    }
                }

                Method currMethod = mMethodsMap.get(sign);
                // 方法匹配失敗
                if (currMethod == null) {
                    return getReturn(jsonStr, 500, "not found method(" + sign + ") with valid parameters");
                }
                // 數字型別細分匹配
                if (numIndex > 0) {
                    Class[] methodTypes = currMethod.getParameterTypes();
                    int currIndex;
                    Class currCls;
                    while (numIndex > 0) {
                        currIndex = (numIndex - numIndex / 10 * 10) - 1;
                        currCls = methodTypes[currIndex];
                        if (currCls == int.class) {
                            values[currIndex] = argsVals.getInt(currIndex);
                        } else if (currCls == long.class) {
                            //WARN: argsJson.getLong(k + defValue) will return a bigger incorrect number
                            values[currIndex] = Long.parseLong(argsVals.getString(currIndex));
                        } else {
                            values[currIndex] = argsVals.getDouble(currIndex);
                        }
                        // Log.e("print",currIndex+"=numIndex="+numIndex+" value:"+ values[currIndex]);
                        numIndex /= 10;
                    }
                }
                </span><span style="font-size:24px;color:#ff0000;">return getReturn(jsonStr, 200, currMethod.invoke(mInstance, values));</span><span style="font-size:14px;">
            } catch (Exception e) {
                //優先返回詳細的錯誤資訊
                if (e.getCause() != null) {
                    return getReturn(jsonStr, 500, "method execute error:" + e.getCause().getMessage());
                }
                return getReturn(jsonStr, 500, "method execute error:" + e.getMessage());
            }
        } else {
            return getReturn(jsonStr, 500, "call data empty");
        }
    }</span>