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