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

關(guān)于跨域與同源,你造嗎?
產(chǎn)品妹子臉憋的通紅,一個勁兒的搖著頭,委屈的小聲說:“唉呀,前端開發(fā)說目前情況是產(chǎn)生了「跨域」問題,瀏覽器有「同源策略」保證安全性,突破不了,改動成本非常高,可是不改也不行啊,用戶在線上反饋幾天了,老大可生氣了,我可怎么辦啊,老大會不會以后不喜歡我了,嗚嗚嗚”。
此時,正是我裝逼的好時光,于是我一個箭(賤)步,跳到她面前,“哭毛啊,哥在這兒呢,好好說話~”。
「同源策略」「跨域」在前端開發(fā)(通常前端都是跟瀏覽器打交道哦,因為更靠近用戶,更多的將后臺數(shù)據(jù)展示給用戶,所以叫前端)中,是很基本的常識,很多沒做過前端開發(fā)的程序員其實也不是很了解這種策略和場景(注意,沒有鄙視的意思,請不要亂扣帽子),更不用說很多產(chǎn)品同學(xué),為了不再被忽悠,請聽我九淺一深的解讀。
先說iframe
首先說說iframe,iframe是html中的一個標(biāo)簽,它可以指定一個隨意的Url地址,比如我寫了個網(wǎng)頁是www.a.com/index.html,內(nèi)容如下:
iframe里面的src字段為www.qq.com,那這個網(wǎng)頁打開之后,會看到騰訊網(wǎng)整個頁面嵌入到了我寫的這個index.html網(wǎng)頁當(dāng)中,iframe的意義非常簡單,就是將一個Url地址嵌入到當(dāng)前頁面并展示出來。
你給遠方的情郎寫了一封情書,當(dāng)把郵票貼在信封右上角的時候,信封為頁面,郵票可以想象為一個iframe標(biāo)簽,它里面也描寫很多內(nèi)容(有山,有水,有人家)。
其中信封是在超市買的,郵票是在郵局買的,它倆生產(chǎn)廠家,品牌,材質(zhì),毫不相干,但組合在一起可以發(fā)揮作用。信封屬于“超市”這個域,郵票屬于“郵局”這個域。
有這樣一種需求,一個網(wǎng)站有3個展示頁面,每個頁面都有一個評論區(qū),那這個評論區(qū)可以封裝為一個url,并用iframe嵌入到每個不同的頁面當(dāng)中去,全局復(fù)用一套評論區(qū)的代碼,節(jié)省程序員,邏輯又好維護,只要一個人實現(xiàn)就可以了哦。
這就是iframe大概的用途,嵌入另一個頁面,兩個頁面功能可以解耦和,不依賴對方而存在。
再說跨域
還是上面貼出來那一段簡單代碼,我已經(jīng)寫好了一個網(wǎng)頁,跟騰訊網(wǎng)一模一樣哦。
我動了壞心思,假設(shè)我有渠道能搞來流量,為啥我不在當(dāng)前頁面當(dāng)中替換掉騰訊網(wǎng)的廣告位置,而變成我的廣告呢,靠這些流量不就把錢掙了嘛,而且用戶也沒什么感知,商業(yè)體驗兩不誤,有沒有任何的服務(wù)器和流量的花銷。
于是我又開始改造代碼了,爭取能完成這個功能,分分鐘走向人生巔峰呢~
這里在<script>標(biāo)簽中,我寫了三句JS代碼來描述整個流程(為了省去調(diào)試的時間,我用中文偽碼代替),如果我真寫了代碼,這個功能也會被瀏覽器拒絕的,會提示「Permission Denied」之類的操作,也就是你無法篡改騰訊網(wǎng)的頁面。
緊扣下小標(biāo)題,當(dāng)前「跨域」操作了。這種情況下瀏覽器直接拒絕掉了這種要求,否則baidu都能操作google頁面了,那互聯(lián)網(wǎng)世界就亂套了。
再再說同源策略
跨域被拒絕,其實是瀏覽器最底層的安全機制稱為「同源策略」,啥是同源呢,建議先復(fù)習(xí)下以前關(guān)于URL的文章把URL五馬分尸,只要協(xié)議,host,端口三個一樣,就是同源的,否則就是非同源的。同源類比為宗教會比較容易理解,伊斯蘭教信奉穆罕穆德,基督教信奉耶穌,這里是一個特征,同源要同時滿足三個特征,舉例如下:
不同源,因為host不同,一個為a.com,另一個為b.com。
不同源,因為協(xié)議不同,一個為http,另一個為https。
不同源,因為端口號不同,一個為80,另一個為81。
同源就是同域,所以才有跨域的說法,也可以說成跨源,一個意思。不同源,證明大家信奉的不是一個宗教。那自然不能修改另一個頁面和拿到另一個頁面相關(guān)的內(nèi)容。只有同源的頁面才可以相互訪問的,因為同源代表了自己本身嘛。
瀏覽器提供了原生的同源機制來保證不同域下的網(wǎng)站互相是隔離的,安全的,正是這種機制的存在,才保證了web生態(tài)下各個網(wǎng)站不亂套。
總結(jié):
從前有一個大戶人家,大老爺牛逼,一輩子掙了不少錢,娶了五房姨太太,老大到老五各有各的心思,都惦記著大老爺那點錢兒,請問這種情況下,雖然大家住在一個大院里面,名義上是一家人,但是各家財務(wù)都是自負(fù)盈虧、獨立結(jié)算,誰也不能把手伸到別人家去。
大老爺心知肚明光靠說是不管用的,必須要立家法,如果哪房姨太太手伸到別人家去了或者紅杏出墻了,那就沒收一切財產(chǎn),并掃地出門,這是大老爺最后的底線。
大老爺就是瀏覽器,制定了一套規(guī)則(同源策略),五個姨太太(網(wǎng)頁或網(wǎng)站)誰也不能偷到別人的財產(chǎn),也不能去別人家搗亂,五個姨太太生活的平平穩(wěn)穩(wěn),誰也不打擾誰。
但日子長了,五位太太還是閑不住的,東家長西家短的開始有了攀比之心和壞心思,她們注定是要交流的
- 我平時都用大寶,你的化妝品是啥牌子的?
- 你的LV是A貨吧,我只背GUCCL的
- 快來看看我這50克拉的鉆石
但是老爺又有規(guī)矩,不讓她們交流,這咋辦呢?
這也引出了最后一個問題,瀏覽器天生是拒絕非同源的網(wǎng)頁溝通的,但是溝通需求無處不在。
比如上面舉了個評論區(qū)的例子,如果評論區(qū)是iframe,當(dāng)有一個新評論的時候,主頁面要展示評論數(shù)+1,這個時候就產(chǎn)生了溝通的需求。一面是拒絕的,一面又要突破限制,似乎是矛盾的,你要玩兒欲擒故縱嘛,親~~~
其實不沖突的,同源策略最基本的保證了域之間的隔離,如果要產(chǎn)生溝通,是要用一些附加的方法來實現(xiàn)的,比如后臺的配合,兩個網(wǎng)站之間的配合。就像有些國家本來是法律上拒絕同性戀的,但是如果雙方愿意,也不反對。
合理的用于跨域溝通的方法有以下幾種:
- JSONP
- iframe document.domain
- iframe location.hash
- HTML5 PostMessage
重點說下第4種,這是新的Html5規(guī)范,規(guī)定了跨域問題的解決辦法,并且是異步的,大部分瀏覽器已經(jīng)支持了,前面幾種有一點hack的感覺,而且有的方法有些局限性,重點推薦第4種。如果你不知道這幾種都是什么方案,用度娘查下,好多博客已經(jīng)講的比較清楚了,不墨跡了,有興趣可以深入了解下。
如果從事產(chǎn)品工作,能知道跨域和同源的基本概念,并且知道為什么產(chǎn)生了這個問題,當(dāng)前是什么狀態(tài),大概的解決方案是什么,你就已經(jīng)很優(yōu)秀了,你是最棒的~
#專欄作家#
給產(chǎn)品經(jīng)理講技術(shù),微信公眾號(pm_teacher),人人都是產(chǎn)品經(jīng)理專欄作家。資深程序猿,專注客戶端開發(fā)若干年,對前端、后臺技術(shù)略懂,熱衷于對新的科技領(lǐng)域的探索。
本文原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自PEXELS,基于CC0協(xié)議
愛你~
比喻是亮點~ ??
寫得不錯的
沒看懂