級別: 中級
要 克儉
(
kjyao@cn.ibm.com
), 軟件工程師, IBM
金 發(fā)華
(
jinfahua@cn.ibm.com
), 軟件工程師, IBM
2008 年 11 月 07 日
HTTP請求的攔截技術可以廣泛地應用在反向代理、攔截 Ajax通信、網頁的在線翻譯、網站改版重構等方面。而攔截根據(jù)位置可以分為服務器端和客戶端兩大類,客戶端攔截借助 JavaScript腳本技術可以方便地和瀏覽器的解釋器及用戶的操作進行交互,能夠實現(xiàn)一些服務器端攔截不容易實現(xiàn)的功能。本文將重點介紹通過 JavaScript腳本在客戶端對頁面內容進行攔截修改的一些原理和技術。
隨著互聯(lián)網應用及 B/S 架構的軟件系統(tǒng)的風行,越來越多的基于瀏覽器的應用得以開發(fā)和部署。對已經上線的應用系統(tǒng)進行攔截和跟蹤可以方便、快捷地實現(xiàn)很多功能。例如,
- IBM 的 Tivoli Access Manager 單點登錄(SSO,關于更多 TAM 的信息,請參見本文后附的資源列表)就是基于逆向代理服務器的原理實現(xiàn)的,逆向代理服務器的實現(xiàn)必須要對既有頁面中的一些 URL 進行攔截和改寫;
- 現(xiàn)今一些有趣的匿名代理服務器也是根據(jù)逆向代理服務器的原理實現(xiàn)的(如 http://www.youhide.com/),這類網站也有 URL 改寫的需求;
- 另外,IBM 提供的在線翻譯網頁的服務中,為了能夠讓被翻譯頁面的鏈接所指向的頁面在用戶交互時繼續(xù)得到翻譯,我們同樣需要使用 URL 的攔截和改寫功能。
不僅僅是 URL 改寫,通過攔截和跟蹤技術可以在極小修改或者使用反向代理不修改原網頁的前提下為基于 BS 的 Web 應用提供更復雜的頁面改寫,腳本改寫等功能。
![]() ![]() |
![]()
|
如圖 1 所示,傳統(tǒng)的 Web 訪問模型通過瀏覽器向 HTTP 服務器獲取 Web 數(shù)據(jù),瀏覽器將獲取的數(shù)據(jù)進行解釋渲染,得到用戶的客戶端界面。
而在帶有服務器端和瀏覽器端跟蹤和攔截的訪問模型中,傳統(tǒng)的訪問方式發(fā)生了變化。服務器端和瀏覽器端的跟蹤和攔截將頁面中的攔截對象,在適當?shù)臄r截時機進行了攔截變化,導致用戶面前的瀏覽器的解釋渲染結果和 HTTP 服務器上的內容存在了邏輯上的差異,而這種差異恰巧是 HTTP Server所需要的結果,而不方便將差異部署在 HTTP Server 上。 Server trace可以作為反向代理服務器的一項邏輯功能存在,Browser trace 是通過腳本完成在客戶端攔截和跟蹤行為。
![]() ![]() |
![]()
|
服務器端實現(xiàn)和客戶端瀏覽器實現(xiàn)的比較
攔截根據(jù)位置可以分為服務器端和客戶端兩大類,客戶端攔截借助 JavaScript 腳本技術可以方便地和瀏覽器的解釋器和用戶的操作進行交互,能夠實現(xiàn)一些服務器端攔截不容易實現(xiàn)的功能。如果將服務器端和客戶端攔截融合在一起,可以很好地處理攔截和跟蹤問題。
功能比較 | 服務器端攔截 | 客戶端攔截 |
向頁面頭部插入代碼 | 強。簡潔,無需逐個加入代碼 | 麻煩。需要逐個為頁面加代碼 |
訪問資源的權限 | 強。可以訪問跨域資源。 | 受限。瀏覽器間有差異 |
會話的控制和訪問 | 強。可以使用相應 API 。 | 受限。需要使用 cookie |
頁面 HTML 的攔截和跟蹤 | 一般。通過正則跟蹤。 | 強。可以使用 DOM 操作 |
頁面腳本的攔截和跟蹤 | 一般。通過正則跟蹤 | 強。可以利用解釋器環(huán)境 |
跟蹤用戶的交互行為 | 一般。通過正則跟蹤 | 強。可以利用瀏覽器事件 |
從表 1 可以看出服務器端攔截和客戶端攔截具有很強的互補性,服務器端攔截擅長服務器 -瀏覽器的通信控制、資源的訪問以及批量頁面的操作,瀏覽器端攔截可以依靠 Script解釋器的環(huán)境,擅長個體頁面的邏輯攔截和跟蹤。本文因篇幅限制,主要針對使用 JavaScript 的瀏覽器端的攔截和跟蹤進行介紹。不過在進入具體的實現(xiàn)之前,先介紹幾個術語。
攔截對象指的是需要被處理的元素,可能包括 [HTML 標簽 ],[HTML 標簽的屬性 ],[ 腳本變量 ],[ 對象 ],[ 函數(shù) ] 等。攔截對象 和 攔截時機 就構成了一個個非常實際的功能或用途。
功能:攔截頁面中的所有鏈接,將其 href 屬性的值 xxx 改為 http://proxyhost/agent?url=xxx
攔截對象 : <A> 標簽
攔截時機:根據(jù)需要適當選擇
功能:攔截頁面中的 document.write 的功能,在調用此函數(shù)前修改函數(shù)參數(shù)
攔截對象 : 對象方法
攔截時機:根據(jù)需要適當選擇
功能 : 攔截頁面中用戶自定義的函數(shù) functionA 的調用
攔截對象: 用戶自定義函數(shù)
攔截時機 : 根據(jù)需要適當選擇
插入點 : 插入點指的是攔截腳本 (JavaScript) 植入頁面文件的位置。
攔截時機 : 攔截時機從頁面的載入過程可以分為 [ 頁面加載前 ],[ 頁面加載中 ],[ 頁面加載后 ] 。
通常來說,在頁面加載后進行處理代碼相對簡單,但是功能也相對受限。頁面加載前處理代碼實現(xiàn)相對復雜,但是功能相對豐富。用戶可以根據(jù)需要混合使用。
從用戶的角度出發(fā),自然希望插入點簡單,攔截時機和攔截點豐富。 因此本文的討論的攔截和跟蹤的技術的出發(fā)點也就明了了,即 : 在盡可能少的對原有系統(tǒng)的改變的前提下,通過 JavaScript 代碼跟蹤并改變系統(tǒng)的行為與內容。
攔截時機的實現(xiàn)
攔截時機中講到的 [ 頁面加載前 ] 是指在用戶的 page 內容被瀏覽器解釋前進行攔截的時機。這種攔截可以在用戶沒有看到渲染結果的時候完成攔截修改,這種技術將在第五種方法中詳細介紹。
[ 頁面加載中 ] 攔截通常是將代碼放在頁面中合適的位置,實現(xiàn)代碼簡單,但是代碼的插入點 ( 也就是頁面的合適位置 ) 可能阻礙了這種時機的使用頻度,也違背了本文的初衷。因此 [ 頁面加載中 ] 的攔截時機通常使用 [ 頁面加載前 ] 的攔截時機進行替代。
例如 : 某 Web 頁面的第 100 行有如下內容:
<script>function userFunction() { //do some actions }</script> |
在頁面的第 200 行調用了上面定義的函數(shù),如:
<script>userFunction(); <script> |
第 200 行的腳本會在頁面的渲染過程中發(fā)生作用,如果希望攔截的話,就需要在第 100 行后,200 行前對 userFunction 進行覆蓋,這樣就會在頁面的加載過程中完成攔截。這種做法嚴重依賴代碼的插入點,因此使用效果不好。
[ 頁面加載后 ] 攔截,首先在這里介紹,實現(xiàn)簡單,能實現(xiàn)很多功能。
方法 : 通常在頁面的尾部 </body> 標簽前,加入:
<script type= "text/javascript" src="lib.js" ></script> |
在 lib.js 文件中,通過改變 window.onload 的定義來構建我們的代碼入口。為了保持功能,建議首先保存原來的函數(shù)的指針。典型的實現(xiàn)代碼可以參考如下 :
var oldOnload = window.onload; window.onload = function() { //code to insert if(oldOnload != null) { oldOnload(); } } |
在文件末尾 </body> 前植入代碼,是為了盡量防止其他加載代碼的覆蓋,如果不考慮加載過程中的代碼覆蓋的話,也可以考慮將代碼放在頁面的相對靠前的位置。
只要不是在加載過程中執(zhí)行的代碼和效果都可以考慮通過 [ 頁面加載后 ]這種攔截時機實現(xiàn)。這種代碼的結構簡單,可以很好的執(zhí)行攔截和跟蹤任務。特別是針對函數(shù)覆蓋這種需求,通常情況下,onload事件之前系統(tǒng)已經加載好所需要的 script 定義的函數(shù)和類,因此 onload事件中的代碼覆蓋可以起到很好的作用。下面介紹的幾種方法都可以首先考慮這種攔截時機。
常見用法 : 在代碼的插入位置,可以植入一些 DOM 的操作,來實現(xiàn)頁面的變化。
例如 : 遍歷 DOM Tree, 修改特定 Node 的特定屬性,或者在特定位置插入新的 Node 等等。
![]() ![]() |
![]()
|
在瀏覽器端的攔截和跟蹤主要是利用 JavaScript 的腳本環(huán)境完成,根據(jù)筆者的經驗,主要尋找并總結了如下的方法。這些方法的使用效果和支持平臺可以互相彌補。
名稱 | 特點 | 優(yōu)點 | 缺點 |
利用瀏覽器的 Event | 通過對 [ 鼠標事件 ],[ 鍵盤事件 ],[HTML 事件 ],[Mutation 事件 ] 的監(jiān)聽,可以對用戶的交互,頁面的變化,特別是標簽節(jié)點的變化做出響應 | 瀏覽器自身支持,代碼量小,幾乎可以用來控制所有的 HTML 內容 | 此方法中的 Mutation Event,F(xiàn)irefox2.0 平臺已支持,IE6.0 尚未支持 |
通過 AOP 技術攔截 | 可以攔截大部分對象的方法調用。 | 很多 JS 代碼庫和框架已經支持 AOP 技術,代碼簡單 | ActiveX 對象無法有效攔截。無法攔截普通的函數(shù)。另外單獨使用此項技術會造成插入點復雜。 |
覆蓋函數(shù)進行攔截 | 通過編寫同名方法覆蓋系統(tǒng)定義,用戶自定義的函數(shù) ( 構造函數(shù) ),達到攔截目的,對普通函數(shù)的攔截是對 AOP 的補充。 | 不依賴其他的代碼庫和 JS 框架,對系統(tǒng)函數(shù)的覆蓋有很好的效果,可以攔截構造函數(shù)用來控制對象的生成。 | 攔截自定義函數(shù)會造成插入點復雜 |
通過動態(tài)代理進行攔截 | 主要用來解決 ActiveX 對象的攔截問題,通過構造 ActiveX 對象的代理對象,實現(xiàn)攔截和跟蹤。 | 典型的例子如 IE 平臺下 AJAX 通信的攔截 | 代碼復雜,屬性更新的同步機制可能導致某些應用異常。 |
通過自代理和 HTML 解析進行攔截 | 此方法主要解決的是攔截時機的問題,配合上面的方法,就可以實現(xiàn)很多功能,而不必要等待頁面的 onload 事件。 | 實現(xiàn)瀏覽器端頁面加載前攔截的好方法 | 代碼復雜 |
利用瀏覽器的 Event
瀏覽器的事件也可以很好地用來攔截和跟蹤頁面。 鼠標和鍵盤的交互事件這里暫不介紹。比較常用的是 onload,onunload 事件和Mutation Events 事件。 onload 和 onunload 事件可以作用在 window,frame,img 和 object等對象上,利用 onload 可以在對象載入前執(zhí)行一些操作 ,onunload 事件可以跟蹤瀏覽器關閉前執(zhí)行操作。
在瀏覽器的 Event 中,Mutation Eventsii 是更加重要的跟蹤工具之一。 Mutation Events 是 DOM2.0標準的一部分,目前 Firefox2.x 已經開始支持 Mutation Events, IE6.0 目前尚不支持。 在 IE6.0中可以是通過使用 onpropertychange 事件及覆蓋節(jié)點的方法彌補部分的不足。這里重點介紹一下 Mutation Events 。
Mutation Event 主要包括了七種事件,如下所示。
- DOMAttrModified:跟蹤 DOM 節(jié)點屬性的變化;
- DOMCharacterDataModified:DOM 節(jié)點字符數(shù)據(jù)的變化;
- DOMNodeInserted:DOM 新節(jié)點被插入到給定的父節(jié)點;
- DOMNodeInsertedIntoDocument:DOM 節(jié)點被直接或隨著祖先節(jié)點而插入;
- DOMNodeRemoved:DOM 節(jié)點被從父節(jié)點刪除;
- DOMNodeRemovedFromDocument:DOM 節(jié)點被直接或跟隨祖先節(jié)點被刪除;
- DOMSubtreeModified:DOM 元素或文檔變化。
可以說利用 Onload 事件的攔截,我們基本上解決了靜態(tài) HTML 內容的攔截,而對于腳本操作的 HTML 變化,我們就可以通過 Mutation Event 來進行解決。
下面類似的實現(xiàn)框架可以用來跟蹤 src、action、href 等屬性的變化。
document.addEventListener("DOMAttrModified", AttributeNodeModified, false); function AttributeNodeModified(evt) { if(evt.attrName == "href") { } if(evt.attrName == "src") { } if(evt.attrName == "action") { } } |
通過 DOMAttrModified、DOMNodeInserted 等事件可以很好地跟蹤和攔截 HTML 的變化。只可惜在 IE6.0平臺上還不能支持 Mutation Event,導致在 IE6.0 上進行攔截和跟蹤的效果大打折扣。針對此平臺,通過覆蓋document.write/DomNode.appendChild/DomNode.insertBefore 等方法和利用onpropertychange 事件可以有限度地支持攔截和跟蹤 HTML。
通過 AOP 技術攔截
針對對象方法調用的攔截,比較成熟的方案是使用 JavaScript 平臺下的 AOP 技術。
目前,JavaScript 平臺上的 AOP 方案主要有 Ajaxpectiii、jQuery AOPiv、Dojo AOPv等。這些代碼庫主要功能是給指定對象的指定方法添加 Before, After,Around 等通知,從而達到攔截對象方法調用的目的 ,并且支持正則搜索方法名稱。
Ajaxpect 的示例代碼如下 :
var thing = { makeGreeting: function(text) { return 'Hello ' + text + '!'; } } function aopizeAdvice(args) { args[0] = 'AOP ' + args[0];return args; } function shoutAdvice(result) { return result.toUpperCase(); } Ajaxpect.addBefore(thing, 'makeGreeting', aopizeAdvice); Ajaxpect.addAfter(thing, /make*/, shoutAdvice); |
當然,在不方便使用上述代碼庫并且需求簡單的時候,我們同樣可以通過對象的方法覆蓋的方式達到同樣的效果。但是無論 AOP 還是方法覆蓋, 都存在一個問題,就是攔截代碼的插入點不能做到很簡捷,因為攔截代碼的存在位置直接影響了代碼的執(zhí)行效果,因此在使用上還有一定的不方便。另外,針對 IE 平臺的ActiveX 對象,代碼庫不能很好的發(fā)揮功效,這是一些不足的地方。
覆蓋系統(tǒng)類 / 方法進行攔截
覆蓋已定義的函數(shù)是一種比 AOP 更直接的攔截和跟蹤腳本調用的方式。
其原理是在原函數(shù)定義后,調用前通過定義同名函數(shù),達到攔截和跟蹤的目的。其一般形式多如下面 :
1: var oriFunction = someFunction; 2: someFunction = function () { 3: return oriFunction(); //or oriFunction.call(x,); 4: } |
第一步是(第一行代碼)為了將指向原來函數(shù)的指針保存,以便后續(xù)使用。
第二步便是定義同名函數(shù),在同名函數(shù)里面的適當位置調用原來的功能。這種方法不但可以跟蹤原來函數(shù),還可以修改和過濾函數(shù)的參數(shù),甚至可以修改返回值。當需要操縱參數(shù)的時候,只需在新定義的函數(shù)中訪問 arguments 對象即可。
例如:針對系統(tǒng)函數(shù) 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 窗口 。
函數(shù)覆蓋的適用范圍較廣,不但可以模擬 AOP 的實現(xiàn),還可以對非對象函數(shù)進行操作。函數(shù)覆蓋可以根據(jù)使用的差異分成若干情況 :
- 覆蓋系統(tǒng)定義的函數(shù)、對象的方法:覆蓋系統(tǒng)定義的函數(shù)或方法可以不用顧及代碼插入點的問題,大可以將函數(shù)覆蓋的代碼放置在頁面的最前邊,并參照上面的形式進行操作。但是特別注意在 IE 平臺下對 ActiveX 的對象的方法無效。
- 覆蓋用戶自定義的函數(shù)、對象的方法:覆蓋用戶自定義的函數(shù),對象的方法需要考慮代碼插入點的問題。正確的代碼插入點的位置應該是在原函數(shù)定義之后,調用之前。
-
覆蓋構造函數(shù):覆蓋構造函數(shù)是滿足上面兩種情況的一種特殊使用形式,跟蹤對象創(chuàng)建之除,可以有效地針對對象的需要作出各種特殊的設置。
覆蓋構造函數(shù)的一般形式 :
var oriFunction = someFunction; someFunction = function () { temp = oriFunction(); //oriFunction.call(x,); return temp; }
下面結合動態(tài)代理的方法給出 IE/Firefox 平臺的 Ajax 通信攔截的一種簡單實現(xiàn)。
Ajax通信的核心是通過 XMLHttpRequest 對象和 HTTP Server 進行通信 ( 同步 / 異步 ),F(xiàn)irefox 和 IE平臺對 XMLHttpRequest 對象的實現(xiàn)不一樣,因此兩種瀏覽器的攔截方案也大相徑庭。我們通過上面的技術將對XMLHttpRequest 對象的方法進行跟蹤。
攔截方法調用,我們可以使用 AOP,當然也可以直接覆蓋函數(shù)。
在 Firefox 平臺,我們可以通過下面的代碼實現(xiàn)攔截 Ajax 對象的通信:
var oriXOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method,url,asncFlag,user,password) { //code to trace or intercept oriXOpen.call(this,method,url,asncFlag,user,password); }; |
但是在 IE 6.0 平臺,上面的代碼將不會有作用,因為在 IE 6.0 平臺,Ajax 通信對象是通過 ActiveX 對象完成的,JS 中的函數(shù)覆蓋不能起到作用。
通過動態(tài)代理進行攔截
當在 IE6.0 平臺遭遇 ActiveX 對象的時候,面對直接的函數(shù)覆蓋不能奏效的時候,我們可以考慮通過另外一種辦法,即動態(tài)代理 ActiveX 對象的方式實現(xiàn)攔截和跟蹤。
首先我們通過覆蓋構造函數(shù)的方法,將創(chuàng)建 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; }; |
我們將構造過程攔截下來后,進行自己的改造,主要操作是創(chuàng)建對象,對象中設置與 ActiveX 對象相同的屬性和方法,并且還需要同步屬性方法。
function createActiveXAgent(ao) { var agent = new Object; 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) { //code to trace and intercept; 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對象的方法。而更關鍵的屬性問題,是通過在函數(shù)調用前后的屬性同步函數(shù)實現(xiàn)的。即:在調用代理內核方法之前,將屬性從代理對象同步給內核對象;在內核方法調用之后,將屬性從內核對象同步給代理對象。
因為 AJAX 對象的屬性幾乎不被用戶寫入,故上面的實現(xiàn)只需要單向屬性同步,即將內核屬性同步給代理屬性。對于復雜的應用,可以通過雙向屬性同步函數(shù)來解決屬性的代理問題。
這種動態(tài)代理的方法將 ActiveX 對象像果核一樣包裹起來,通過代理對象自身的同名屬性和方法提供給外界進行訪問,從而達到跟蹤和攔截的目的。
通過自代理和 HTML 解析進行攔截
當代碼攔截點需要簡單可靠的時候,上面的方法無法很好的滿足需求。于是我們需要新的思路來解決代碼的攔截點問題。
自代理和 HTML 解析是通過攔截原有的 HTTP 通信,通過重新通信獲得內容后,在瀏覽器解析前通過我們自己的代碼進行簡單解析過濾的方式進行代碼處理的方案。
首先是攔截原有的解析,重新加載新的內容:
var s = document.location.href; var comm = new ActiveXObject("Microsoft.XMLHTTP"); comm.open('get',s,false); comm.onreadystatechange = function() { if(comm.readyState == 4) { document.execCommand("stop"); var retText = removeMe(comm.responseText); retText = processContent(retText); } } comm.send(null); |
如果將上面的代碼寫在一個 js 文件里,然后通過 <script> 標簽插入到頁面的最開始位置(<HTML> 后面)。
在IE6.0 的瀏覽器下面,上面的代碼因為使用了 XMLHTTP 的同步通信機制,因此代碼會阻塞在 comm.send(null)處,當通信結束得到完整的頁面之后,會觸發(fā) stop 導致瀏覽器停止解析,轉而執(zhí)行我們的 processContent. removeMe的意義在于重新獲得的片面中去除這段代碼自身,防止無窮迭代。
在 Firefox 下,我們需要使用 window.stop 代替上面的 execCommand.
當我們搶在瀏覽器之前拿到 HTML 內容后,我們下面的任務就是分析 HTML. 目前尚沒有成熟的 JS 分析 HTML 的框架。因此我們可以選擇將 HTML 轉換成 XML, 然后借助 DOM 進行分析,也可以實現(xiàn)我們自己的 HTML 分析方案 .
我們可以將 HTML 的頁面分析成節(jié)點如下的一顆樹:
節(jié)點 { 父節(jié)點 ; 屬性個數(shù) ; 屬性集合 ; 子節(jié)點個數(shù) ; 子節(jié)點集合 } |
圖 2 是個簡單的 HTML 文本分析狀態(tài)圖,不支持 HTML 的 & 字符串拼接功能。可以反復調用這個模塊用來從 HTML 文檔中提取字符塊生成相應的節(jié)點,然后可以利用 JavaScript 的正則表達時提取節(jié)點的屬性。
通過 HTML 文本分析狀態(tài)圖可以得到 HTML 解析的代碼,然后得到一個根為 root的節(jié)點。后面對樹進行進一步的處理,就可以實現(xiàn)很多攔截功能。比如 function覆蓋。前面講到的用戶自定義函數(shù)覆蓋會受到代碼插入點復雜的影響。如果在這種方法的攔截下,就可以實現(xiàn)分析出 <script>節(jié)點的內容中含有特定的 function 定義,進而替換或者在其后插入新的函數(shù)定義,不會造成插入點復雜的結果。
![]() ![]() |
![]()
|
通過上面的介紹,可以看出發(fā)揮 JavaScript 的優(yōu)勢,我們能夠很好的控制頁面的加載過程,在不需要二進制瀏覽器插件的情況下,僅僅通過腳本對Web 內面的邏輯攔截是可行的。這種方法在反向代理、網站的改版重構、以及不方便對原有內容進行直接改動的場合是十分有益的。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
