2012-02-22 44 views
21

在實際嘗試使用ajax方法之前,有沒有「安全」的方法來檢查相同的來源策略是否適用於URL?以下是我有:檢查是否應用相同的來源策略

function testSameOrigin(url) { 

    var loc = window.location, 
     a = document.createElement('a'); 

    a.href = url; 

    return a.hostname == loc.hostname && 
      a.port == loc.port && 
      a.protocol == loc.protocol; 
} 

這種類型的作品,但它是一種基於該wikipedia article手動猜測。有沒有更好的方法預先檢查跨域補貼? jQuery可以使用。

+0

如果你做了一個跨域請求,它將會失敗,'readystate = 4'和'statuscode = 0',這與中止請求類似。 既然你需要防範中止請求,爲什麼你需要這個檢查?我覺得這個安全措施是從外部強制執行的,你無法控制它,所以從環境中的任何檢查在定義上都是錯誤的。所以我認爲你不應該檢查它,只是讓請求失敗。 – Halcyon 2012-03-03 20:38:12

回答

8

有趣的問題!我四處搜尋,找不到任何其他東西,但是當我亂搞一些測試代碼時,我遇到了這個問題。如果你只是想要一個簡單的方式來測試一個URL而不提出請求,我會按照你的方式來做。如果你不關心的是判斷一個請求,你可以試試這個:

做一個簡單的Ajax請求,任何你想要的網址:

var ajaxRequest = $.ajax({ 
    url: 'http://www.google.com', 
    async: false 
}); 

它返回一個jqXHR對象,然後你可以檢查:

ajaxRequest.isRejected(); // or... 
ajaxRequest.isResolved(); 

現在,唯一的問題是,isRejected()將評估爲true爲每一個情況下無法載入網頁(即404未找到,等),但你可以檢查狀態代碼:

ajaxRequest.status; 

它看起來像上面的一行將返回0當你試圖打破同源策略,但它會返回在其他情況下,適當的錯誤代碼(再次,即404)。

所以包裹起來,也許你可以嘗試做這樣的事情:

function testSameOrigin(testUrl) { 

    var ajaxRequest = $.ajax({ 
    url: testUrl, 
    async: false 
    }); 

    return ajaxRequest.isRejected() && ajaxRequest.status === 0; 
} 

沒有一個明確的答案,以任何方式,但我希望它可以幫助你找出你在找什麼!

+0

是的,這是一個有趣的方法。在我最初的情況下,我想通過嘗試「驗證」URL來擺脫在執行拒絕的ajax調用時遇到的令人討厭的控制檯錯誤。我還剛剛發現,在本地文件(文件:協議)上執行ajax請求也每次都失敗。所以這是另一種情況下檢查... – David 2012-02-29 23:37:24

+0

您可以通過將'isLocal'標誌設置爲'true' http://api.jquery.com/jQuery來爲本地文件使用ajax。阿賈克斯/ jQuery的#阿賈克斯的設置 – Steve 2012-03-01 03:11:28

0

另一種執行跨域腳本的方法是使用JSON-P。 您也可以閱讀這個article。 否則,相同的源策略不允許跨域腳本。

+0

我不確定爲什麼所有的答案都是關於如何製作或不製作跨瀏覽器ajax請求,這根本就不是我所要求的...我需要更清楚嗎? – David 2012-02-29 00:17:24

10

在實際嘗試使用ajax方法之前,有沒有「安全」的方法來檢查相同的原始策略是否適用於URL?以下是我有:

function testSameOrigin(url) { 

    var loc = window.location, 
     a = document.createElement('a'); 

    a.href = url; 

    return a.hostname == loc.hostname && 
      a.port == loc.port && 
      a.protocol == loc.protocol; 
} 

這是做這件事的安全可靠的方式,只要你正在做的(或者說沒有做)某些事情。

這類作品,但它是一種基於維基百科文章的手動猜測。

這應該在「正常」情況下完全工作。如果您打算使用cross-domain scripting,則需要對其進行修改。

如果在腳本中修改了document.domain,例如從「foo.example.com」和「bar.example.com」更改爲「example」。COM http://example.com‘其中實際上它應該返回true」你testSameOrigin功能將爲返回false’。

如果您在修改document.domain計劃,您可以添加只需在腳本中添加該支票。

如果您打算使用CORS(請參閱上面的鏈接)來允許跨域通信,它也會返回一個錯誤的否定信息,但是如果您使用的是CORS,則會列出可與之通信的域名列表,而您可以將該列表添加到該功能中。

是否有預先檢查跨域補貼的更好方法? jQuery可以使用。

或許不會,但它可能是值得一提的是你在控制檯從史蒂夫的回答看可能是「觀測者的困境」 ......這些錯誤看起來像他們從控制檯試圖檢查所產生的其他窗口,不一定來自腳本。

假設你不打算使用document.domain或使用CORS,你的原始解決方案可能會更好,因爲它不需要額外的請求來確定服務器是否可用。即使你正在做一些跨域腳本,修改你現在可以適應的功能也許是你最好的選擇。

+1

,而這是檢查CORS的好辦法要求它打破了在IE7而產生的錨不會返回任何信息有關的鏈接,例如在IE7它評估等環節''將返回'a.href =>「main.html」'''a.hostname =>「」'等我仍然試圖找出如何處理這在IE7 tho。但找不到任何好的解決方案。因爲它永遠不會創建完整的href。 – zanona 2012-08-29 15:07:45

+0

你會添加什麼document.domain檢查?簡單地用'document.domain'替換'loc.hostname'是否正確? – 2014-07-07 20:03:39

+0

@BT'a.hostname'仍然是「foo.example.com」,「document.domain」只是「example.com」。它必須是一個特殊情況檢查,即如果你知道你正在將'document.domain'重寫爲「example.com」,則主機名檢查將類似於'a.hostname == loc.hostname || a.hostname ==「foo.example.com」' – 2014-07-07 21:04:58

0

大廈關閉Dagg Nabbit的回答,這似乎多了幾分齊全:

function sameOrigin(url) { 
    var loc = window.location, a = document.createElement('a') 
    a.href = url 

    return a.hostname === loc.hostname && 
      a.port === loc.port && 
      a.protocol === loc.protocol && 
      loc.protocol !== 'file:' 
} 

告誡我能想到的:

1

嘗試這種解決方案也是如此。

function csrfSafeMethod(method) { 
    // these HTTP methods do not require CSRF protection 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 

function sameOrigin(url) { 
    // test that a given url is a same-origin URL 
    // url could be relative or scheme relative or absolute 
    var host = window.document.location.host; // host + port 
    var protocol = window.document.location.protocol; 
    var srOrigin = '//' + host; 
    var origin = protocol + srOrigin; 
    // Allow absolute or scheme relative URLs to same origin 
    return (url === origin || url.slice(0, origin.length + 1) === origin + '/') || 
    (url === srOrigin || url.slice(0, srOrigin.length + 1) === srOrigin + '/') || 
    // or any other URL that isn't scheme relative or absolute i.e relative. 
    !(/^(\/\/|http:|https:).*/.test(url)); 
} 

// if you want to check before you make a call 
if (!csrfSafeMethod(data.type) && sameOrigin(data.url)) { 
    // ... 
} 

// or if you want to set csrf token 
$.ajax({ 
    beforeSend: function (xhr, settings) { 
    if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) { 
     xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken")); 
    } 
    } 
});