浏覽器基本原理
我叫小風,是Windows帝國一個普通的上班族。
今天,我入職了一家浏覽器公司,公司的主營業務是為人類提供Internet上網服務,我的崗位是負責執行JavaScript代碼。
上午的晨會上,認識了負責網絡連接配接的老白,所有網絡請求都得找他幫忙,還有負責存儲管理的小黑,什麼
Cookie
,
LocalStorage
SessionStorage
之類的都歸他管。哦,差點忘了,還有一個妹子小雪,她負責網頁渲染。
随後主管安排了我的工作:老白從網絡取回網頁之後交給小雪來解析渲染,遇到網頁中的JavaScript代碼的時候,就由我來處理執行這些代碼。
聽完主管的安排,我心裡美滋滋,因為工作上需要密切配合,主管把我和小雪妹子的工位安排在了一起,想想都開心_||
坐下不久,我主動和小雪聊了起來。
“小雪,你平時工作都做些什麼啊?”
小雪轉過身來,“我呀,就負責把老白給我的HTML檔案進行解析,建構DOM樹,然後再拿到CSS檔案,建構CSSOM樹,最後把網頁給畫出來”
我似懂非懂的點了點頭,正想繼續找話題,這時,老白過來了。
“小雪,來活了,這是剛剛拿到的網頁檔案,快處理一下”
小雪轉過身去開始忙碌了起來,不一會兒,她就停下來說到:“小風哥,有 <script> 标簽了,該你上了”
看來該是我露一手的機會了,我拿到 <script> 中的代碼,開始忙活起來,很快就完成了,繼續交給小雪完成下面的工作。
就這樣你來我往了幾個回合,我有些嫌麻煩:“小雪,要不你先一次處理完,我最後再來統一執行所有的 <script> 标簽中的代碼,這樣不是省事一點嘛”
“那可不行,你在執行JavaScript的時候有可能會去修改我建構的DOM樹的内容,咱倆必須按順序來,不然會出亂子的”,小雪一本正經的說到。
沒辦法,隻好聽她的。
就這樣,我們一直配合的有條不紊,還時不時去找老白發送下資料,找小黑索要Cookie,很快就和大家混熟了。就這樣過了幾天,沒想到平靜的工作起了波瀾······
跨域禁止
這天我拿到了一段代碼,需要去請求一段資料,老規矩,我準備好了請求參數找到老白,準備讓他給我發出去。
沒想到老白一看大驚:“這是一個跨域請求啊,不能發出去!”
我愣了一下,“跨域請求?什麼鬼”
老白指着我給的請求參數說到:“你看你給的這個請求URL,和你現在處理的這個網頁URL,不是一家人啊,域名不一樣”
“你管人家是不是一家人,發出去不就得了,快點,我還等着要呢”
“不行,知道你這個崗位之前那位怎麼走的不?就是因為他在一個山寨網銀網站裡面執行JavaScript的時候向真正的銀行網站發起了轉賬請求,把人家的錢給搞丢了。就因為這個被老闆開了,我要不是平日裡跟老闆走得近,說不定也要連坐。”
聽了老白的話,我吓得不輕,差點飯碗就不保了,不過我心裡還是有一些疑問。
“老白,為什麼真正的銀行網站會信任這個山寨網站的請求呢?”
“因為這人之前剛好也打開了真實的銀行網站,還設定了Cookie讓小黑儲存着。這後面山寨網站的請求發出去時,Cookie也一并帶上了,網站那端還以為是正常的請求呢,這不就遭了嗎。這種攻擊方式被叫做
CSRF,跨站請求僞造
”,老白說到。
“那後來呢?後來怎麼樣了?”,我繼續問到。
“後來,後來就把那小子炒掉了啊,這不才給你騰了個坑嗎!不過公司為了防止以後此類事情再次發生,就制定了一個禁止跨域請求的規定!”
老白一邊說,一邊給我講了起來什麼是禁止跨域請求。
我這才知道,原來請求的目标URL和所在網頁的URL的協定、域名、端口有一個不同,就算是跨域了。
今天幸好有老白,要不然我好不容易得來的工作就要丢了。告别了老白,回到工位,我抛了一個禁止跨域請求的錯誤就沒管了。
不過,沒過多久,公司就收到了很多投訴,說我們打開的網頁排版格式全部錯亂了,有時候甚至連圖檔都加載不出來。
最後追責到了小雪妹子這裡,小雪很委屈的說到:“這不能怪我啊,他們好多網頁都引用了外部的css和js檔案,尤其那個叫
jQuery
的最多。但是每次找到老白要這些檔案,老白都以公司的禁止跨域請求的規定拒絕給我,我也沒有辦法啊”
沒辦法,公司隻好對跨域請求的規定作了一輪修訂,規定了以後通過HTML标簽引入外部檔案的時候予以放行,具體來說有:
- <img>:引入外部圖檔
- <link>:引入外部css
- <script>:引入外部javascript
- ......
規則修訂後,投訴總算變少了,渲染的網頁也逐漸恢複了正常。
跨域:JSONP
然而太平日子沒過多久,投訴又多了起來。我一打聽才知道,原來現在開始流行什麼前後端分離技術,資料和展示解耦,資料不再直接放在網頁檔案裡,而是需要單獨通過JavaScript去從伺服器拿回來動态展示。
問題出在這些網站的前端網頁和業務資料接口伺服器常常不在一起,分屬不同的域名或者使用不同的端口,違反了我們的跨域禁令,導緻資料請求不到,頁面經常一片空白,沒有資料。
上司為這事兒左右為難,既想盡快處理這些投訴,又不想放棄安全原則放開這些跨域的請求。
就在這時,經驗老道的老白獻了一策:“既然規則中允許從外部JS檔案,我們何不就利用它來實作外部接口的請求呢?”
我們幾個都滿臉問号,不解其意。老白接着說到:“我畫個圖你們就明白了”
我看着老白畫的圖,才明白他說的什麼意思,“老白,好計策啊,利用規則中對<script>标簽請求的放行将請求發出去,然後讓伺服器傳回經過callback函數包裝的JS代碼,最後實作資料的加載!”
“小風你很聰明哦”,老白得意的點點頭。
“不過人家伺服器憑什麼傳回你需要的格式?”,小雪問到。
老白撓了撓頭,“額,這個嘛,就需要伺服器那邊配合咱們一下啦”
“你這個好像隻能支援GET請求吧,遇到
POST
、
PUT
DELETE
這些請求咋辦呢?”,我也提了一個問題。
老白的臉一下就變色了,“這個,這個,好像是有這個問題,不過先湊合用着嘛,他們天天投訴你們不嫌煩嘛”
經過讨論,我們還是打算把這套方案先推出去,因為需要這些網站背景的配合,他們大部分都不太情願,不過迫于沒有其他方案,在我們的遊說之下還是勉強同意了。
為了友善推廣,我們還給這門技術取了一個名字:
JSONP
,就是
JSON with Padding
的意思。
跨域:CORS
漸漸地,投訴變少了,不過奇怪的是,公司的上網業務也變少了。一打聽才知道,人類都不用我們了,用上了隔壁的Chrome浏覽器。
負責打探消息的老白回來了,“不好了,咱們的JSONP技術大家都不用了,轉投隔壁Chrome浏覽器的
CORS
技術了”
上司一聽急了,“這是啥技術,能比我們的JSONP還好?”
老白激動的說到,“是啊,上司,這CORS全稱叫
跨域資源共享(Cross-origin resource sharing)
,不像咱們那樣投機取巧實作,走得是正規路子,而且還解決了隻支援GET請求的問題,什麼請求都能發”
“你快說說,他們到底怎麼搞的?”
老白來到畫闆前,開始畫起圖來,一邊畫一邊給大家講解:“他們在正式的跨域請求之前,先發送了一個
OPTIONS
請求去詢問伺服器是否允許接下來的跨域請求”
“OPTIONS?你要不說我都忘記HTTP協定裡還有這麼一種請求了”,我笑着說道。
“這怎麼個詢問法呢?”,上司鄒着眉頭問。
老白繼續說到,“他們和那些網站伺服器商定了一下,在OPTIONS請求裡新增了幾個字段:”
-
:發起請求原來的域Origin
-
:将要發起的跨域請求方式(GET/PUT/POST/DELETE/······)Access-Control-Request-Method
-
:将要發起的跨域請求中包含的請求頭字段Access-Control-Request-Headers
“伺服器在響應字段中來表明是否允許這個跨域請求,浏覽器收到後檢查如果不符合要求,就拒絕後面的請求”
-
:允許哪些域來通路(*表示允許所有域的請求)Access-Control-Allow-Origin
-
:允許哪些請求方式Access-Control-Allow-Methods
-
:允許哪些請求頭字段Access-Control-Allow-Headers
-
:是否允許攜帶CookieAccess-Control-Allow-Credentials
老白說完,圖也畫完了:
“每次都要發起詢問,好費事哦”,小雪看着圖說到。
老白搖頭說到:“唉,小雪說到點上了,為了避免每次都要詢問,他們還做了兩個重要的優化呢”
見我們都伸直了脖子等待答案,老白緩了緩才繼續說到:“第一,如果是一個簡單請求,那就直接發起請求,隻需在請求中加入Origin字段表明自己來源,在響應中檢查Access-Control-Allow-Origin,如果不符合要求就報錯,不需要再單獨詢問了”
“那什麼是簡單請求呢?”,我問到。
“簡單請求就是請求方式屬于HEAD、GET、POST三者之一,請求頭隻有下面這些,不符合要求的就是非簡單請求,就得詢問了”
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:(application/x-www-form-urlencoded、multipart/form-data、text/plain)
“那第二個優化又是什麼呢?”
“前面的伺服器響應字段中我少說了一個,還有一個Access-Control-Max-Age,它表明了這個詢問結果的有效期,後面浏覽器在有效期内也可以不必再次詢問”
聽完老白的講解,大家都紛紛點贊,這比我們的JSONP方式不知道高到哪裡去了。
上司當即決定咱們也要支援這種跨域方式,盡快減少公司的損失。
我們幾個趕緊行動,加了幾天班總算把這套方案給實作了。功夫不負有心人,咱們的業務又慢慢有了起色。
未完待續······
彩蛋
早上,我剛到公司,小雪妹子就轉過頭告訴我:“風哥,主管讓你去趟他的辦公室,他好像不太高興,你當心點”
“你知道是什麼事情嗎?”
“我也不太清楚,隻聽說你執行了什麼錯誤的JavaScript代碼”
我心裡一緊,感覺大事不妙
預知後事如何,請關注後續精彩······
往期熱門回顧
就為了一個原子操作,其他CPU核心都罷工了
完了!CPU一味求快出事兒了!
可怕!CPU竟成了黑客的幫兇!
哈希表哪家強?幾大程式設計語言吵起來了!
核心位址空間大冒險4:線程切換
震撼!全網第一張源碼分析全景圖揭秘Nginx
一個整數+1引發的災難
一網打盡!每個程式猿都該了解的黑客技術大彙總
DDoS攻擊:無限戰争
一個Java對象的回憶錄:垃圾回收
誰動了你的HTTPS流量?
路由器裡的廣告秘密
一個HTTP資料包的奇幻之旅
我是一個流氓軟體線程