最近操作WebView遇到的些许问题,记录贴

又再一次给webView杠上了,APP内开一个入口加上一个H5界面,界面中有些许交互。本来很简单的问题,估工期还是算上 开产品会时并没有明确交互的功能点,所以要了两天的时间。但是没有想到简单的问题,自己还是持续采坑。

首先加密,APP内登陆,传递给js 登陆信息。H5内容是一个PK活动,可能考虑到防止黑客恶意攻击等问题,对于传递APP用户信息做了加密处理。定制最终方案是 MD5( 时间戳分钟级加盐)+MD5+HmacSha256

这里记录下写的一个工具:MD5( 时间戳分钟级加盐)+MD5+HmacSha256

public class Md5Utils {

    /**
     * 16位MD5加密
     * 实际是截取的32位加密结果的中间部分(8-24位)
     *
     * @param content
     * @return
     */
    public static String md5Decode16(String content) {
        return md5Decode32(content).substring(8, 24);
    }

    /**
     * 32位MD5加密
     *
     * @param content -- 待加密内容
     * @return
     */
    public static String md5Decode32(String content) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("NoSuchAlgorithmException", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UnsupportedEncodingException", e);
        }
        //对生成的16字节数组进行补零操作
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10) {
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }

    private static String hmacSha(String KEY, String VALUE, String SHA_TYPE) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE);
            Mac mac = Mac.getInstance(SHA_TYPE);
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8"));

            byte[] hexArray = {
                    (byte) '0', (byte) '1', (byte) '2', (byte) '3',
                    (byte) '4', (byte) '5', (byte) '6', (byte) '7',
                    (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
                    (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
            };
            byte[] hexChars = new byte[rawHmac.length * 2];
            for (int j = 0; j < rawHmac.length; j++) {
                int v = rawHmac[j] & 0xFF;
                hexChars[j * 2] = hexArray[v >>> 4];
                hexChars[j * 2 + 1] = hexArray[v & 0x0F];
            }
            return new String(hexChars);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static String hmacSha(Context context, String token) {
        String key = ((System.currentTimeMillis()) + "");// 时间搓
        String time = TimeUtilsJ.stampTomonth(key);  // 转时间格式
        String month = null;
        try {
            month =( TimeUtilsJ.dateToLongMonth(time) / 1000 )+"";  // 转分钟
        } catch (ParseException e) {
            e.printStackTrace();
        }
        String mToken = token + "epk";
        String md51 = md5Decode32(mToken);
        String md52 = md5Decode32(md51);
        String sha = hmacSha(month, md52, "HmacSHA256");
        return sha;

    }


}

问题二:

传递参数,排除loadUrl  直接拼接,采用WebView 网络接口拦截 POST请求,把参数拼接进请求头中的形式。(但是最终由于一些问题,Android还是才用了直接拼接传单)

遇到问题,无法把参数塞进请求头 目前没有解决,后续关注。

先把自己尝试的过程记录一下,为以后填坑打基础。

WebViewClient 提供很多有用的功能,这里不做详细说明,有兴趣的可以自行百度。

这里找到一篇具体讲解的

我使用具体功能是拦截

shouldInterceptRequest

我对这个方法的理解,拦截WebView中加载的一切请求,get,post。可以return null 的情况是自己程序不处理,还是给WebView 自行处理,返回有数据,是自己处理接口,并可以把接口返还给WebView 呈现出来。

这个方法有两个重载方法,

已经过时,Google 不推荐使用

public WebResourceResponse shouldInterceptRequest(WebView view, String url)

推荐使用

public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request)

就是这个方法, 让我发愁了一天。

 

这个是过时的方法处理,由于网上都是这样写的,虽然没有达到我想要的效果,不过还是记录下

            @SuppressLint("NewApi")
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                if (url.contains("")) {
                    URL urlStr = null;
                    try {
                        urlStr = new URL(url );
                        URLConnection rulConnection = urlStr.openConnection();
                        HttpURLConnection conn = (HttpURLConnection) rulConnection;
                        conn.setRequestProperty("Accept-Charset", "utf-8");
                        conn.setRequestProperty("contentType", "utf-8");
                        conn.setRequestMethod("POST");
                        // Read input
                        String charset = conn.getContentEncoding() != null ? conn.getContentEncoding() : Charset.defaultCharset().displayName();
                        String mime = conn.getContentType();
                        InputStream isContents = conn.getInputStream();
                        StringBuilder sb = new StringBuilder();
                        String s; // 依次循环,至到读的值为空
                        BufferedReader reader = new BufferedReader(new InputStreamReader(isContents, "UTF-8")); // 实例化输入流,并获取网页代码
                        while ((s = reader.readLine()) != null) {
                            sb.append(s);
                        }
                        isContents.close();

                        String str = sb.toString();
                        Log.e("----------------",str);
                        return new WebResourceResponse(mime, charset,
                                isContents);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                } else {
                    return super.shouldInterceptRequest(view, url);
                }
            }

 

            @SuppressLint("NewApi")
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
                if (request.getUrl().toString().contains("")) {
                    request.getRequestHeaders().put("token", "");
                    request.getRequestHeaders().put("isApp", "");
                    Log.e("-----------------", request.getRequestHeaders() + "\n" + request.getUrl() + "\n" + request.getMethod());
                    return shouldInterceptRequest(view, request);
                }
                return super.shouldInterceptRequest(view, request);
            }

理论上这样编写,应该是可以解决我遇到的问题,从代码结构上,很直观的感觉是拿到 request的请求,然后把自己需要拼接的参数放进request中,然后在把请求转给 shouldInterceptRequest 进行处理, 从中转前 打印,request 也显示已经拼接,

但是自己使用Fiddler 抓吧显示,请求中并没有加入参数。所以压根无效。这里我就郁闷了,不知道怎么处理,所以换了一种写法

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
class WebResourceRequest1 implements WebResourceRequest {
    WebResourceRequest request;

    public WebResourceRequest1(WebResourceRequest request) {
        this.request = request;
    }

    @Override
    public Uri getUrl() {
        return Uri.parse(request.getUrl().toString());
    }

    @SuppressLint("NewApi")
    @Override
    public boolean isForMainFrame() {
        return request.isForMainFrame();
    }

    @Override
    public boolean isRedirect() {
        return true;
    }

    @SuppressLint("NewApi")
    @Override
    public boolean hasGesture() {
        return request.hasGesture();
    }

    @SuppressLint("NewApi")
    @Override
    public String getMethod() {
        Log.e("--------------", request.getMethod());

        return request.getMethod();
    }

    @SuppressLint("NewApi")
    @Override
    public Map<String, String> getRequestHeaders() {
        Map<String, String> map = request.getRequestHeaders();
        map.put("token", "");
        map.put("isApp", "");
        Log.e("--------------", "进入map");
        return map;
    }
}

依然无效。

然后自己开始Goole ,没有找到任何有效的解决办法,所以大神们,请求你们的帮助,

 

记录需求:移动端加载WebView ,H5生命周期一起动就 post一个后端接口,请求用户数据。而我要拦截的就是这个post 因为前段请求这个接口的时候并没有放入token ,需要移动端添加token,

按照IOS 说法 中间人模式(这里我要吐槽 - 碰到一个时时刻刻要显示自己很优秀的同事,我很无奈。我一直觉得,开发之间特别是我们这种两端没有任何利益纠葛,你好我好大家好,谁没有一点采坑的经历,但是你就是非要搞得全公司皆知,这个方案我进行不了等等云云的。)就我们这个app,虽然目前是做活动,但是被黑客攻击的机率感觉就像中大奖一样,并且传递token经过加密处理了。破解收益和付出完全不成正比。

好了前面吐槽,谁让自己嘴皮子不利索,被怼的体无完肤,承认自己不懂还不行。这块有空专研下,目前还是抓紧把任务完成-

 

抽空记录

 

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