一、HTTP 请求的拦截技术可以广泛地应用在反向代理、拦截 Ajax 通信、网页的在线翻译、网站改版重构等方面。而拦截根据位置可以分为服务器端和客户端两大类,客户端拦截借助 JavaScript 脚本技术可以方便地和浏览器的解释器及用户的操作进行交互,能够实现一些服务器端拦截不容易实现的功能。本文将重点介绍通过 JavaScript 脚本在客户端对页面内容进行拦截修改的一些原理和技术

二、方法简介

名称

特点

优点

缺点

利用浏览器的 Event

通过对 [ 鼠标事件 ],[ 键盘事件 ],[HTML 事件 ],[Mutation 事件 ] 的监听,可以对用户的交互,页面的变化,特别是标签节点的变化做出响应

浏览器自身支持,代码量小,几乎可以用来控制所有的 HTML 内容

此方法中的 Mutation Event,Firefox2.0 平台已支持,IE6.0 尚未支持

通过 AOP 技术拦截

可以拦截大部分对象的方法调用。

很多 JS 代码库和框架已经支持 AOP 技术,代码简单

ActiveX 对象无法有效拦截。无法拦截普通的函数。另外单独使用此项技术会造成插入点复杂。

覆盖函数进行拦截

通过编写同名方法覆盖系统定义,用户自定义的函数 ( 构造函数 ),达到拦截目的,对普通函数的拦截是对 AOP 的补充。

不依赖其他的代码库和 JS 框架,对系统函数的覆盖有很好的效果,可以拦截构造函数用来控制对象的生成。

拦截自定义函数会造成插入点复杂

通过动态代理进行拦截

主要用来解决 ActiveX 对象的拦截问题,通过构造 ActiveX 对象的代理对象,实现拦截和跟踪。

典型的例子如 IE 平台下 AJAX 通信的拦截

代码复杂,属性更新的同步机制可能导致某些应用异常。

通过自代理和 HTML 解析进行拦截

此方法主要解决的是拦截时机的问题,配合上面的方法,就可以实现很多功能,而不必要等待页面的 onload 事件。

实现浏览器端页面加载前拦截的好方法

代码复杂

三、方法的实现

1、覆盖系统类 / 方法进行拦截

覆盖已定义的函数是在原函数定义后,调用前通过定义同名函数,达到拦截和跟踪的目的。其一般形式多如下面 :

var oriFunction = someFunction;

someFunction = function () {

return oriFunction(); //or  oriFunction.call(x,);

}

第一步是(第一行代码)为了将指向原来函数的指针保存,以便后续使用。

第二步便是定义同名函数,在同名函数里面的适当位置调用原来的功能。这种方法不但可以跟踪原来函数,还可以修改和过滤函数的参数,甚至可以修改返回值。当需要操纵参数的时候,只需在新定义的函数中访问 arguments 对象即可。

例如:针对系统函数 window.open(URL,name,specs,replace) 我们可以通过下面的代码进行拦截:

var oriWindowOpen = window.open;

window.open = function(url,names,specs,replace)  {

url = "http://www.ibm.com"; //or arguments[0]="http://www.ibm.com";

return oriWindowOpen(url,names,specs,replace);

}

上面的拦截会导致所有的 window.open 调用全部打开 http://www.ibm.com 窗口 。

函数覆盖的适用范围较广,不但可以模拟 AOP 的实现,还可以对非对象函数进行操作。函数覆盖可以根据使用的差异分成若干情况 :

  • 覆盖系统定义的函数、对象的方法:覆盖系统定义的函数或方法可以不用顾及代码插入点的问题,大可以将函数覆盖的代码放置在页面的最前边,并参照上面的形式进行操作。但是特别注意在 IE 平台下对 ActiveX 的对象的方法无效。
  • 覆盖用户自定义的函数、对象的方法:覆盖用户自定义的函数,对象的方法需要考虑代码插入点的问题。正确的代码插入点的位置应该是在原函数定义之后,调用之前。
  • 覆盖构造函数:覆盖构造函数是满足上面两种情况的一种特殊使用形式,跟踪对象创建之除,可以有效地针对对象的需要作出各种特殊的设置。

覆盖构造函数的一般形式 :

var oriFunction = someFunction;

someFunction = function () {

temp = oriFunction(); //oriFunction.call(x,);

return temp;

}

2、通过动态代理进行拦截

当在 IE6.0 平台遭遇 ActiveX 对象的时候,面对直接的函数覆盖不能奏效的时候,我们可以考虑通过另外一种办法,即动态代理 ActiveX 对象的方式实现拦截和跟踪。

首先我们通过覆盖构造函数的方法,将创建 XMLHttpRequest 对象的过程进行改造。

var oriActiveXObject = ActiveXObject;

ActiveXObject = function(param) {

var obj = new oriActiveXObject(param);

if(param == "Microsoft.XMLHTTP" ||

param=="Msxml2.XMLHTTP" ||

param == "Msxml2.XMLHTTP.4.0") {

return createActiveXAgent(obj);

}

return obj;

};

我们将构造过程拦截下来后,进行自己的改造,主要操作是创建对象,对象中设置与 ActiveX 对象相同的属性和方法,并且还需要同步属性方法。

function createActiveXAgent(ao) {

var agent = newObject;

agent.activeXObject = ao; //被包裹的内核,是真正的通信对象

agent.syncAttribute = function() { //syncAttribute是用来同步属性的

try{

this.readyState = this.activeXObject.readystate;

this.responseText = this.activeXObject.responseText;

this.responseXML = this.activeXObject.responseXML;

this.status = this.activeXObject.status;

this.statusText = this.activeXObject.statusText;

}catch(e) { }

};

agent.trigStateChange = function() { //模拟onreadystatechange

agent.syncAttribute();

if(agent.onreadystatechange != null) {

agent.onreadystatechange();

}

};

agent.activeXObject.onreadystatechange = agent.trigStateChange;

agent.abort = function() { //模拟abort

this.activeXObject.abort();

this.syncAttribute();

};

agent.getAllResponseHeaders =function()   { //模拟内核对应的方法

var result = this.activeXObject.getAllResponseHeaders();

this.syncAttribute();

return result;

};

agent.getResponseHeader = function(headerLabel) { //模拟内核对应的方法

var result = this.activeXObject.getResponseHeader(headerLabel);

this.syncAttribute();

return result;

};

agent.open = function(method,url,asyncFlag,userName,password) {

//codetotraceandintercept;

url=getParamURL(url,method);

this.activeXObject.open(method,url,asyncFlag,userName,password);

this.syncAttribute();

};

agent.send = function(content) { //模拟内核对应的方法

this.activeXObject.send(content);

this.syncAttribute();

};

agent.setRequestHeader = function (label,value) { //模拟内核对应的方法

this.activeXObject.setRequestHeader(label,value);

this.syncAttribute();

};

return agent;

};

从上面的代码可以看出来,代理对象通过自身的方法模拟了原来 ActiveX 对象的方法。而更关键的属性问题,是通过在函数调用前后的属性同步函数实现的。即:在调用代理内核方法之前,将属性从代理对象同步给内核对象;在内核方法调用之后,将属性从内核对象同步给代理对象。

因为 AJAX 对象的属性几乎不被用户写入,故上面的实现只需要单向属性同步,即将内核属性同步给代理属性。对于复杂的应用,可以通过双向属性同步函数来解决属性的代理问题。

这种动态代理的方法将 ActiveX 对象像果核一样包裹起来,通过代理对象自身的同名属性和方法提供给外界进行访问,从而达到跟踪和拦截的目的。

拦截和跟踪HTTP请求的主要方法及实现的更多相关文章

  1. 使用 JavaScript 拦截和跟踪浏览器中的 HTTP 请求

    HTTP 请求的拦截技术可以广泛地应用在反向代理.拦截 Ajax 通信.网页的在线翻译.网站改版重构等方面.而拦截根据位置可以分为服务器端和客户端两大类,客户端拦截借助 JavaScript 脚本技术 ...

  2. Retrofit2 + OkHttp3设置Http请求头(Headers)方法汇总

    在构建网络层时会遇到一个问题就是要手动配置Http请求的Headers,写入缓存Cookie,自定义的User-Agent等参数,但是对于有几十个接口的网络层,我才不想用注解配置Headers,目前网 ...

  3. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 >>>>>>>>>>>>>>&g ...

  4. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求   Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java ...

  5. 【spring源码学习】springMVC之映射,拦截器解析,请求数据注入解析,DispatcherServlet执行过程

    [一]springMVC之url和bean映射原理和源码解析 映射基本过程 (1)springMVC配置映射,需要在xml配置文件中配置<mvc:annotation-driven >  ...

  6. 使用NSURLProtocol和NSURLSession拦截UIWebView的HTTP请求(包括ajax请求)

    问题:服务器端有一个网站需要AD认证,整站都开了Basic认证,包括图片,CSS等资源,我在HTTP请求头里面添加认证所需的用户名和密码,传递到服务器端可以认证通过.我在UIWebView的shoul ...

  7. SpringBoot 拦截器获取http请求参数

    SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 目录 SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 获取http请求参数是一种刚需 定义拦截器获取请求 为 ...

  8. 学习axios必知必会(2)~axios基本使用、使用axios前必知细节、axios和实例对象区别、拦截器、取消请求

    一.axios的基本使用: ✿ 使用axios前必知细节: 1.axios 函数对象(可以作为axios(config)函数使用去发送请求,也可以作为对象调用方法axios.request(confi ...

  9. struts2拦截器interceptor的三种配置方法

    1.struts2拦截器interceptor的三种配置方法 方法1. 普通配置法 <struts> <package name="struts2" extend ...

随机推荐

  1. 像Bootstrap一样比较热门的前端框架有哪些

    像Bootstrap一样比较热门的前端框架有哪些 一.总结 一句话总结:框架大同小异,可以多去各自官网看看效果(比较一下各自的不同点(也就是提供的不同的功能)),然后根据需求选择用哪个.我觉得boot ...

  2. C++ Tricks(一)—— 判断字符串 string 对象的所有字符都相等

    S == string(S.size(), S[0]);

  3. swiper如何实现轮播嵌套轮播

    之所以要写这篇文章是因为插件有个bug,要改掉这个bug比较麻烦,所以就想了个折中的办法,绕过这个限制,方法千万条,功能干出来第一条,哈哈 最近做了个需求,效果图是这样的 第一个框是大轮播,第二个框是 ...

  4. 10.14 android输入系统_多点触摸驱动测试及Reader线程、InputStage分析

    21. 多点触摸_电容屏驱动程序_实践_tiny4412 tiny4412触摸屏: 分辨率为800 x 480http://wiki.friendlyarm.com/wiki/index.php/LC ...

  5. 10.7 android输入系统_Dispatcher线程情景分析_Reader线程传递事件和dispatch前处理

    android输入系统C++最上层文件是com_android_serve_input_InputManagerService.cpp global key:按下按键,启动某个APP可以自己指定,修改 ...

  6. iOS图片加载-SDWebImage

    一.SDWebImage内部实现过程 1, 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后  SDWeb ...

  7. 【习题 5-9 UVA - 1596】Bug Hunt

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] map模拟 map<string,int>记录每个数组的大小 map <pair<string, int&g ...

  8. Java 学习(19):Java 多线程编程

    Java 多线程编程 Java 给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特 ...

  9. POJ 3090 Visible Lattice Points (ZOJ 2777)

    http://poj.org/problem?id=3090 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1777 题目大意: ...

  10. CSS Reset的相关概念及实例

    原文 简书原文:https://www.jianshu.com/p/fdb79010895c 大纲 1.什么是css reset? 2.CSS reset的实例 1.什么是css reset? 个人理 ...