淺談同源策略

      網友投稿 813 2025-04-03

      同源策略可能是現代瀏覽器中最重要的安全概念了,它在使得同一站點中各部分頁面之間基本上能夠無限制允許腳本和其他交互的同時,能完全防止不相關的網站之間的任何干涉。現在所有支持 JavaScript 的瀏覽器都會使用這個策略,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。

      我們可以假設一個沒有同源策略的場景:我打開了我自己的銀行賬戶頁面,稱之為 A,之后,我又打開了另一個頁面,我們稱之為 B。如果 B 是一個惡意頁面,那么在沒有同源策略限制的前提下,它可以通過 Javascript 任意修改和訪問 A 中的任何內容。

      一、什么叫做同源

      首先要厘清的是,怎么樣的頁面被稱為同源的頁面——如果兩個頁面的協議、端口以及域名都相同,那這兩個頁面就被稱之為同源,如果其中有一項不同,那也將不會滿足同源的定義。下面是以 http://store.company.com/dir/page.html 這個 URL 為源的一組例子:

      將表格中所有的 URL 與 http://store.company.com/dir/page.html 相比較,我們可以看到:

      第一條和第二條同時滿足了協議、端口和域名相同的條件,所以是同源;

      第三條因為使用的是 https 協議,協議不同,所以不是同源;

      第四條因為使用了 81 端口,端口不同,所以不是同源;

      第五條因為域名,也就是域名不相同,所以不是同源。

      那么為什么會對于同源做出如此嚴格的限制呢,其實是否同源主要是為了防止兩類事件:

      限制跨源腳本的 APIs 的訪問;

      阻止跨源數據存儲的訪問。

      簡單來說就是防止一個惡意界面通過惡意請求去訪問非同源的數據。在發起跨域請求的情況下,我們的瀏覽器會自動的去拒絕這些請求,即使這樣的跨域請求通過了,其返回結果也會被瀏覽器拒絕。

      二、跨源網絡訪問

      同源策略會對于跨域的資源和數據的訪問做出限制。其實在網上很多情況下我們都會需要加載不同源的資源,比如在個人網站中需要插入一張在公共圖床的圖片,這種情況下個人網站和公共圖床上的圖片必然是不同源的,但最后在頁面上能成功的加載圖片并且能夠看到,這又是為什么呢?

      首先,通常情況下同源策略控制跨域的請求會被分為三類:

      跨域寫操作( Cross-origin writes )-- 例如表單提交,通常是被允許的;

      跨域讀操作( Cross-origin reads )-- 例如可以讀取嵌入圖片的高度和寬度,通常是不被允許的;

      跨域資源嵌入( Cross-origin embedding )-- 例如嵌入圖片,通常是被允許的。

      那么可能有哪些資源是可以被跨源嵌入的呢?

      標簽嵌入跨域腳本。語法錯誤信息只能在同源腳本中捕捉到;

      標簽嵌入 CSS。由于 CSS 的松散的語法規則,CSS 的跨域需要一個設置正確的 Content-Type 消息頭;

      嵌入圖片;

      @font-face 引入的字體。一些瀏覽器允許跨域字體( cross-origin fonts ),一些需要同源字體( same-origin fonts );