程序員別唬我系列之:跨域與同源

4 評論 8460 瀏覽 33 收藏 10 分鐘

關于跨域與同源,你造嗎?

產品妹子臉憋的通紅,一個勁兒的搖著頭,委屈的小聲說:“唉呀,前端開發說目前情況是產生了「跨域」問題,瀏覽器有「同源策略」保證安全性,突破不了,改動成本非常高,可是不改也不行啊,用戶在線上反饋幾天了,老大可生氣了,我可怎么辦啊,老大會不會以后不喜歡我了,嗚嗚嗚”。

此時,正是我裝逼的好時光,于是我一個箭(賤)步,跳到她面前,“哭毛啊,哥在這兒呢,好好說話~”。

「同源策略」「跨域」在前端開發(通常前端都是跟瀏覽器打交道哦,因為更靠近用戶,更多的將后臺數據展示給用戶,所以叫前端)中,是很基本的常識,很多沒做過前端開發的程序員其實也不是很了解這種策略和場景(注意,沒有鄙視的意思,請不要亂扣帽子),更不用說很多產品同學,為了不再被忽悠,請聽我九淺一深的解讀。

先說iframe

首先說說iframe,iframe是html中的一個標簽,它可以指定一個隨意的Url地址,比如我寫了個網頁是www.a.com/index.html,內容如下:

iframe里面的src字段為www.qq.com,那這個網頁打開之后,會看到騰訊網整個頁面嵌入到了我寫的這個index.html網頁當中,iframe的意義非常簡單,就是將一個Url地址嵌入到當前頁面并展示出來。

你給遠方的情郎寫了一封情書,當把郵票貼在信封右上角的時候,信封為頁面,郵票可以想象為一個iframe標簽,它里面也描寫很多內容(有山,有水,有人家)。

其中信封是在超市買的,郵票是在郵局買的,它倆生產廠家,品牌,材質,毫不相干,但組合在一起可以發揮作用。信封屬于“超市”這個域,郵票屬于“郵局”這個域。

有這樣一種需求,一個網站有3個展示頁面,每個頁面都有一個評論區,那這個評論區可以封裝為一個url,并用iframe嵌入到每個不同的頁面當中去,全局復用一套評論區的代碼,節省程序員,邏輯又好維護,只要一個人實現就可以了哦。

這就是iframe大概的用途,嵌入另一個頁面,兩個頁面功能可以解耦和,不依賴對方而存在。

再說跨域

還是上面貼出來那一段簡單代碼,我已經寫好了一個網頁,跟騰訊網一模一樣哦。

我動了壞心思,假設我有渠道能搞來流量,為啥我不在當前頁面當中替換掉騰訊網的廣告位置,而變成我的廣告呢,靠這些流量不就把錢掙了嘛,而且用戶也沒什么感知,商業體驗兩不誤,有沒有任何的服務器和流量的花銷。

于是我又開始改造代碼了,爭取能完成這個功能,分分鐘走向人生巔峰呢~

這里在<script>標簽中,我寫了三句JS代碼來描述整個流程(為了省去調試的時間,我用中文偽碼代替),如果我真寫了代碼,這個功能也會被瀏覽器拒絕的,會提示「Permission Denied」之類的操作,也就是你無法篡改騰訊網的頁面。

緊扣下小標題,當前「跨域」操作了。這種情況下瀏覽器直接拒絕掉了這種要求,否則baidu都能操作google頁面了,那互聯網世界就亂套了。

再再說同源策略

跨域被拒絕,其實是瀏覽器最底層的安全機制稱為「同源策略」,啥是同源呢,建議先復習下以前關于URL的文章把URL五馬分尸,只要協議,host,端口三個一樣,就是同源的,否則就是非同源的。同源類比為宗教會比較容易理解,伊斯蘭教信奉穆罕穆德,基督教信奉耶穌,這里是一個特征,同源要同時滿足三個特征,舉例如下:

http://www.a.com/index.html

http://www.b.com/index.html

不同源,因為host不同,一個為a.com,另一個為b.com。

http://www.a.com/index.html

https://www.a.com/index.html

不同源,因為協議不同,一個為http,另一個為https。

https://www.a.com:80/index.html

https://www.a.com:81/index.html

不同源,因為端口號不同,一個為80,另一個為81。

同源就是同域,所以才有跨域的說法,也可以說成跨源,一個意思。不同源,證明大家信奉的不是一個宗教。那自然不能修改另一個頁面和拿到另一個頁面相關的內容。只有同源的頁面才可以相互訪問的,因為同源代表了自己本身嘛。

瀏覽器提供了原生的同源機制來保證不同域下的網站互相是隔離的,安全的,正是這種機制的存在,才保證了web生態下各個網站不亂套。

總結:

從前有一個大戶人家,大老爺牛逼,一輩子掙了不少錢,娶了五房姨太太,老大到老五各有各的心思,都惦記著大老爺那點錢兒,請問這種情況下,雖然大家住在一個大院里面,名義上是一家人,但是各家財務都是自負盈虧、獨立結算,誰也不能把手伸到別人家去。

大老爺心知肚明光靠說是不管用的,必須要立家法,如果哪房姨太太手伸到別人家去了或者紅杏出墻了,那就沒收一切財產,并掃地出門,這是大老爺最后的底線。

大老爺就是瀏覽器,制定了一套規則(同源策略),五個姨太太(網頁或網站)誰也不能偷到別人的財產,也不能去別人家搗亂,五個姨太太生活的平平穩穩,誰也不打擾誰。

但日子長了,五位太太還是閑不住的,東家長西家短的開始有了攀比之心和壞心思,她們注定是要交流的

  • 我平時都用大寶,你的化妝品是啥牌子的?
  • 你的LV是A貨吧,我只背GUCCL的
  • 快來看看我這50克拉的鉆石

但是老爺又有規矩,不讓她們交流,這咋辦呢?

這也引出了最后一個問題,瀏覽器天生是拒絕非同源的網頁溝通的,但是溝通需求無處不在。

比如上面舉了個評論區的例子,如果評論區是iframe,當有一個新評論的時候,主頁面要展示評論數+1,這個時候就產生了溝通的需求。一面是拒絕的,一面又要突破限制,似乎是矛盾的,你要玩兒欲擒故縱嘛,親~~~

其實不沖突的,同源策略最基本的保證了域之間的隔離,如果要產生溝通,是要用一些附加的方法來實現的,比如后臺的配合,兩個網站之間的配合。就像有些國家本來是法律上拒絕同性戀的,但是如果雙方愿意,也不反對。

合理的用于跨域溝通的方法有以下幾種:

  1. JSONP
  2. iframe document.domain
  3. iframe location.hash
  4. HTML5 PostMessage

重點說下第4種,這是新的Html5規范,規定了跨域問題的解決辦法,并且是異步的,大部分瀏覽器已經支持了,前面幾種有一點hack的感覺,而且有的方法有些局限性,重點推薦第4種。如果你不知道這幾種都是什么方案,用度娘查下,好多博客已經講的比較清楚了,不墨跡了,有興趣可以深入了解下。

如果從事產品工作,能知道跨域和同源的基本概念,并且知道為什么產生了這個問題,當前是什么狀態,大概的解決方案是什么,你就已經很優秀了,你是最棒的~

#專欄作家#

給產品經理講技術,微信公眾號(pm_teacher),人人都是產品經理專欄作家。資深程序猿,專注客戶端開發若干年,對前端、后臺技術略懂,熱衷于對新的科技領域的探索。

本文原創發布于人人都是產品經理。未經許可,禁止轉載。

題圖來自PEXELS,基于CC0協議

更多精彩內容,請關注人人都是產品經理微信公眾號或下載App
評論
評論請登錄
  1. 愛你~

    來自北京 回復
  2. 比喻是亮點~ ??

    來自湖北 回復
  3. 寫得不錯的

    回復
  4. 沒看懂

    回復