什麼是CORS

Wiki百科描述:跨來源資源共享(CORS),用於讓網頁的受限資源能夠被其他域名的頁面存取的一種機制。

簡單來說,JavaScript存取非同域名的資源時伺服器必須明確告知瀏覽器允許何種請求,否則瀏覽器會阻擋並跳出has been blocked by CORS policy.




CORS工作的原理

Wiki百科描述:對於能夠修改資料的Ajax和HTTP請求方法(特別是「 GET」 以外的 HTTP 請求,或者搭配某些 MIME 類型的「 POST」 請求),瀏覽器必須先使用「 OPTIONS」 方法發起一個預檢請求(preflight request),從而獲知伺服器端是否允許該跨源請求。伺服器確認允許之後,才發起實際的 HTTP 請求。在預檢請求的返回中,伺服器端也可以通知客戶端,是否需要攜帶身分憑證(包括 Cookies 和 HTTP 認證相關資料)。





從程式碼的角度觀察CORS的工作原理

首先準備好前端瀏覽器的Request範例直接使用Angular的HttpClient,另外建立一個HttpHeader帶有Content-Type: application/json」,這裡很重要!但我們先記得這個Header帶了什麼即可



接著再準備一個Delphi的WebServer,我們在接收Request的地方寫入一些簡單的Log,然後讓WebServer Response一個200


接下來就執行我們前端的範例程式並且觀察WebServer收到的請求,依照CORS的工作原理Request會是一個「OPTIONS」

💡文章前頭有描述CORS的工作原理,當我們使用Ajax或是HTTP的Request(請求)時,瀏覽器會先發送一個「OPTIONS」的方法跟伺服器做一些驗證這個叫做「預檢請求」,這個驗證讓我們從而獲知伺服器端是否允許該跨源請求,當伺服器確認允許之後才發起實際的 Request(請求)



這時如果Response Header不做任何的設定,瀏覽器就會拋出一大堆奇奇怪怪的CORS錯誤

CORS - 圖1.1


我們Google搜尋一下CORS就會跑出很多解法告訴你說要在Header添加

Access-Control-Allow-Origin: *
我們就依照Google大神的方式添加上方這段程式碼在Response Header裡面


再執行一次前端瀏覽器的程式碼,這時你會發現欸~還是跳了一大堆奇怪的錯誤啊!
CORS - 圖1.2


等等等等!我們冷靜的看一下錯誤訊息可以發現圖1.1和圖1.2的錯誤訊息好像不太一樣了,圖1.1的錯誤訊息是Access-Control-Allow-Origin」而圖1.2的錯誤訊息則是Access-Control-Allow-Headers」,到這裡想起來剛剛要大家記的Request Header裡面添加的東西嗎?沒錯!我們添加了Content-Type」,依照CORS的工作原理我們發送的Request有Content-Type的話WebServer也要Response相對的Content-Type,否則瀏覽器會直接把你的回應阻擋在外哦!


接著我們將Response Header再次調整一下並在下面添加Content-Type,以下為了方便我們就直接把Request POST來的資料直接Response回去就好XD


修改完後再次執行前端瀏覽器的程式碼,此時的Request已經成功得到伺服器的Response了!


最後我們回到WebServer看Log可以發現瀏覽器Request實際上發送了兩次,原來瀏覽器發送Request之前,會先由瀏覽器本身發起「OPTIONS」驗證,驗證成功後才會真正發送我們實際的「POST」 ,以上就是CORS的工作方式了!