iOS开发总结

WKWebview在NSURLProtocol中body丢失问题

2020-03-16  本文已影响0人  Auditore

背景说明

之所以想hook XMLHTTPRequest是因为NSURLProtocol导流WKWebview有body丢失问题。要解决这个问题,目前一个思路,通过注入JS代码的方式来解决这个问题,在NSURLProtocol的didReceiveData函数中,我们可以第一时间接收到请求返回的HTML数据,然后我们把hook XMLHTTPRequest的send方法和open的JS函数插入到HTML之中,然后再返回给系统。

在hook代码里面要重组url和body参数并且加上标识位,然后重新发起get请求,然后这时候我们的NSURLProtocol会再次捕获这个重新发起的get请求,根据我们请求中的标记,辨别出是我们重组过的请求,将请求中的参数取出来(我们把body存放在文件里,做好标识,便于一一对应request,方便读取),再次拼接以后塞入body发起post请求。

1.Hook XMLHTTPRequest

我打算分成两步来进行,第一部分已经完成,第二部分还在进行中。

1.1 hook XMLHTTPRequest发起的请求

XMLHTTPRequest的hook,参考https://github.com/wendux/Ajax-hook 使用起来很简单,把hookAjax函数插入script标签就可以了。如下范例,

<script src="https://unpkg.com/ajax-hook/dist/ajaxhook.min.js"></script>///这行插入到HTML文件的head标签内
///如下内容插入到body标签内
<script>

    hookAjax(
        // hook functions and callbacks of XMLHttpRequest object
        {
            onreadystatechange: function (xhr) {
                console.log("onreadystatechange called: %O", xhr)
                //return true
            },
            onload: function (xhr) {
                console.log("onload called: %O", xhr)
                xhr.responseText = "hook" + xhr.responseText;
                //return true;
            },
            open: function (arg, xhr) {
                console.log("open called: method:%s,url:%s,async:%s", arg[0], arg[1], arg[2], xhr)
                arg[1] += "?hook_tag=1";
                //统一添加请求头

            },
            send: function (arg, xhr) {
                console.log("send called: %O", arg[0])
                xhr.setRequestHeader("_custom_header_", "ajaxhook")
            },
            setRequestHeader: function (arg, xhr) {
                console.log("setRequestHeader called!", arg)
            },

            // hook attributes of XMLHttpRequest object
            timeout: {
                setter: function (v, xhr) {
                    //timeout shouldn't exceed 10s
                    return Math.max(v, 1000);
                }
            }
        }
    );

    $.get().done(function (d) {
        console.log(d.substr(0, 30) + "...")
        //use original XMLHttpRequest
        console.log("unhook")
        unHookAjax()
        $.get().done(function (d) {
            console.log(d.substr(0, 10))
        })

    })

</script>

通过控制台的log,验证后,可以拦截到请求。

1.2 将hook代码接入NSURLProtocol

时间关系,这部分还在验证。这是下个阶段的任务。

2.另一种思路

XMLHTTPRequest是否有设置proxy的方式?如果可行的话,是不是就一步登天了?可惜,并不能,不过,有个老哥提出了另一种方式,https://juejin.im/post/5db85842f265da4d1f51bbda ,这种方式也算是hook的变种。
这种方式待验证.

上一篇 下一篇

猜你喜欢

热点阅读