1

我有一個Chrome擴展,以特殊的方式監視瀏覽器,發送一些數據到Web服務器。在當前配置中,這是本地主機。因此,內容腳本包含這樣的代碼:鉻擴展中的訪問控制 - 允許 - 來源錯誤

var xhr = new XMLHttpRequest(); 
xhr.onreadystatechange = function(data)... 
xhr.open('GET', url, true); 
xhr.send(); 

其中URL參數是 'http://本地主機/ CTRL PARAMS?'(或http://127.0.0.1/ctrl?params - 這並不重要)。

清單文件包含跨站點請求的所有必需權限。

擴展適用於大多數網站很好,但在一個網站上我的錯誤:

XMLHttpRequest cannot load http://localhost/ctrl?params. Origin http://www.thissite.com is not allowed by Access-Control-Allow-Origin.

我已經試過這是這裏提出幾個權限(*://*/*http://*/*<all_urls>),但沒有人幫助解決問題。

所以,問題是這個特定網站可能會出現什麼問題(顯然有可能是其他網站有類似的不當行爲,我想知道這種性質),以及如何解決這個錯誤?

+0

你能更具體地說明哪個網站你看到這個錯誤嗎?它可能使用內容安全策略(https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html)來防止數據被加載。 – 2012-02-05 01:23:45

+0

這裏是網站 - www.wix.com。 – Stan 2012-02-05 08:47:01

+0

Mihai,你是說網站的「內容安全策略」優先於擴展權限?那麼我們怎麼能寫一個可靠的擴展呢?有沒有解決方法? – Stan 2012-02-05 08:50:05

回答

10

(TL;博士:看到兩個可能的解決方法在回答結束)

這是一系列發生的事件,這將導致您看到的行爲:

  1. HTTP: //www.wix.com/開始加載
  2. 它有一個<script>標籤異步加載Facebook連接的腳本:
     
    (function() { 
        var e = document.createElement('script'); 
        e.type = 'text/javascript'; 
        e.src = document.location.protocol + 
        '//connect.facebook.net/en_US/all.js'; 
        e.async = true; 
        document.getElementById('fb-root').appendChild(e); 
    }()); 
    
  3. 一旦HTML(而不是資源,我包括Facebook連接腳本)加載wix.com頁面時,將觸發DOMContentLoaded事件。由於您的內容腳本使用"run_at" : "document_end",因此此時它會被注入並運行。
  4. 您的內容腳本運行下面的代碼(是最好的,我可以告訴大家,它想做load事件觸發後,其大部分工作):
     
    window.onload = function() { 
        // code that eventually does the cross-origin XMLHttpRequest 
    }; 
    
  5. 的Facebook連接的腳本加載,它有它自己load事件處理程序,它在這個片段中補充說:
     
    (function() { 
        var oldonload=window.onload; 
        window.onload=function(){ 
        // Run new onload code 
        if(oldonload) { 
         if(typeof oldonload=='string') { 
         eval(oldonload); 
         } else { 
         oldonload(); 
         } 
        } 
        }; 
    })(); 
    
    (這是第一個關鍵部分)因爲你的腳本設置onload屬性,oldonload是腳本的加載處理。
  6. 最終,所有資源都會被加載,並且會觸發load事件處理程序。
  7. Facebook Connect的load處理程序運行,它運行自己的代碼,然後調用oldonload。 (這是第二個關鍵部分)由於該頁面正在調用load處理函數,因此它不會在腳本的isolated world中運行,而會在頁面的「主要世界」中運行。只有腳本的隔離世界存在跨源XMLHttpRequest訪問權限,所以請求失敗。

若要查看此簡化測試情況下,看到this page(其模擬物http://www.wix.com),它加載this script(其模擬Facebook連接)。我也提出了content scriptextension manifest的簡化版本。

您的load處理程序最終在「主要世界」中運行的事實很可能是Chrome bug 87520(該錯誤具有安全隱患,因此您可能無法看到它)的體現。

有兩種方法來解決此問題:

  1. 而不是使用"run_at" : "document_end"和一個load事件處理程序,你可以使用默認的運行時間(document_idle,文件加載後),只是有你的代碼運行一致。
  2. 而不是通過設置window.onload屬性添加load事件處理程序,請使用window.addEventListener('load', func)。這樣你的事件處理程序就不會被Facebook Connect看到,所以它會在內容腳本的孤立世界中運行。
+2

你是天才。非常感謝。 – Stan 2012-02-12 19:10:06

+0

感謝您的詳細解答! – Shaihi 2012-12-17 23:00:22

1

您看到的訪問控制源問題很可能會顯示在響應的標題(不受控制)中,而不是請求(在您的控制之下)。

訪問控制 - 允許來源是設置在標題中的CORS的策略。使用PHP,例如,您使用套頭的像下面讓CORS:

header('Access-Control-Allow-Origin: http://blah.com'); 
header('Access-Control-Allow-Credentials: true'); 
header('Access-Control-Allow-Headers: Content-Type, Content-Disposition, attachment'); 

如果聽起來像,如果服務器在這頭設置一個特定的原產地,那麼你的Chrome extension是繼指令允許來自該域的跨域(POST?)請求。

+0

如果確認,那麼它看起來像Chrome中的一個錯誤,因爲擴展權限應該允許跨源請求。我認爲這種情況通過'webRequest'涉及「手動」http頭處理是不正常的。 – Stan 2012-02-10 07:23:10

相關問題