CORS了解跨來源資源共享
前言
在做 Chrome Extension 的登入登出的時候,遇到了所謂的 CORS 的問題,當時並沒有了解它本身,只是想盡辦法讓資料成功打到 Server 端並回傳一個資料給 Extension 儲存下來,結束之後決定來深入了解 CORS 是什麼。
了解 CORS 之前先來了解所謂的 同源政策 (Same Origin Policy)
SOP 是由所有瀏覽器實施的安全措施,它不允許從一個來源加載的腳本和資源與另一個來源進行交互。
這是對於 JavaScript 的一個限制。
舉個例子:
你的網站是 http://www.example.com,你無法向 http://www.test.com 發出XHR requests
那為什麼不行就要先了解網域的格式
舉個範例網址:
http://www.example.com/index.html
http/https 是協定、 example.com 是域名、通訊埠( port )通常 http 預設的 port 是80
只要"不同協定"或"域名"或者是"port"都會被認定不同源
http://www.example.com/background.html 認定同源,原因是檔案路徑不影響
https://www.example.com/index.html 認定不同源,原因是不同協定
http://example.com/index.html 認定不同源,原因是不同域名
http://example.com:81/index.html 認定不同源,原因是不同port
了解完 SOP 就來看看什麼是 CORS 。
CORS(跨來源資源共享)
CORS 出現的意義就是為了繞過 SOP , Origin 是 Server 端的網域名單,只要名單內沒有這串網域就會被 SOP 擋住, Server 端也能限制名單內網域用哪些方法例如:
get 或 post
所說的方法有 get
post
options
說了這麼多我們來舉個例子來更了解狀況:
有一天你用 Facebook 點了一個惡意網站,這網站會向 Facebook 提出請求要取你的個人資料, Facebook 發現這位客人不認識而被 SOP 給擋住。
但是 SOP 也僅僅只是對瀏覽器的限制並不會對 Server 禁止訪問, Server 可以進行 cURL 來發出請求或者是 Postman
CORS 請求方式
但是 CORS 有兩種請求方式 simple requests (簡單請求) 和 preflight requests (預檢請求) ,來分析簡單請求和預檢請求差在哪裡
先來討論簡單請求,簡單請求只要符合以下所有條件就是簡單請求:
打 API 的 method 只要是 get 、 post 或 HEAD
Content-Type header:
application/x-www-form-urlencoded multipart/form-data text/plain 這兩個就可以構成大多數的簡單請求的用例,但想知道詳細列表可以到 MDN
預檢請求:
不滿足於簡單請求的條件就是預檢請求,最常看到不滿足條件的要求是:
Cotent-Type: application/json 預檢會以 HTTP 的 options 發出請求到 Server,確認 API 內容是否安全並送出,由於跨站請求可能會攜帶使用者資料 例如: cookie
遇到 CORS 問題,並怎麼操作?
以 Ruby on Rails 為例子:
有個 rake-cors gem Rails 裡來輕鬆操作 CORS 設定
#config/application.rb
config.middleware.insert_before 0, Rack::Cors do
allow do
origins /\Aexample.com\z/ #這就是所說的名單
resource '/api/v1/', headers: :any, methods: [:get, :post, :options] #限制客人這三個方法能用哪幾個來拜訪我的網站
end
end
結論
我們在過程知道了什麼是 SOP 和 CORS ,也知道瀏覽器針對不同的 header 針對 CORS 處理 API 的不同方式,最後也研究了對 Server 端怎麼操作 CORS 解決跨來源請求的錯誤。