# CORS - 從熟悉的錯誤訊息開始 ``` - request has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. ``` - 什麼是跨來源? 跨來源的英文是 cross origin,顧名思義,當你想要從來源 A 去拿來源 B 的東西,就是跨來源。 1. origin = scheme + host +/****(don't care) + port https://huli.tw 跟 https://huli.tw/api 同源,因為 scheme + host + port 都一樣(/api 是 path 的部分,不是 host) https://huli.tw 跟 http://huli.tw 不同源,因為 scheme 不一樣 http://huli.tw 跟 http://huli.tw:3000 不同源,因為 port 不一樣 https://api.huli.tw 跟 https://data.huli.tw 不同源,因為 host 不一樣 https://huli.tw 跟 https://api.huli.tw 不同源,因為 host 不一樣 - 為什麼不能跨來源呼叫 API? - 精確:為什麼不能用 XMLHttpRequest 或是 fetch(或也可以簡單稱作 AJAX)獲取跨來源的資源? - 常見的跨來源 - 'img src="https://another-domain.com/bg.png" /' - <script src="https://another-domain.com/script.js" /> - 如果沒有跨來源阻擋的話 - 假設公司有的內部網域 http://prox.internal.com ,外部無法連進去,只有內網的人可以連入, - 並且我寫了一個網站,並且使用AJAX指令 get prox.internal.com/client-id/details - 取的資料後,傳回自己的server - 這種攻擊方式稱為:跨站請求偽造 CRFS - 取得內部網站很難嗎? ``` =javascript // 發出 request 得到資料 function sendRequest(url, callback) { const request = new XMLHttpRequest(); request.open('GET', url, true); request.onload = function() { callback(this.response); } request.send(); } // 嘗試針對每一個 port 拿資料,拿到就送回去我的 server for (let port = 80; port < 10000; port++) { sendRequest('http://localhost:' + port, data => { // 把資料送回我的 server }) } ``` - 所以CORS限制=就是安全性考量 # 正確認識跨來源請求 - 第一步 為什麼瀏覽器要把這些擋住? - 第二步 怎麼擋的? 1.  2. CORS 限制的其實是「拿不到 response」,而不是「發不出 request」。 前端解法: 1.關掉瀏覽器的安全性設置 - 只對自己瀏覽器有效 2.把 fetch mode 設成 no-cors - 自欺欺人(意思並不是「繞過 cors 拿到資料」,而是「我知道它過不了 cors,但我沒差,所以不要給我錯誤也不要給我 response」) 3.不要用 AJAX 拿資料 - 需要 server 特別支援而且有其限制。 **真正的解法:請後端設置 CORS header** # 簡單請求VS 非簡單請求 - 簡單請求:只要 method 是 GET、POST 或是 HEAD 然後不要帶自訂的 header - 非簡單請求 會多送出 preflight request,「預檢請求」。 - 瀏覽器會幫忙帶上兩個 header: - Access-Control-Request-Headers - Access-Control-Request-Method - preflight 就是一個驗證機制,確保後端知道前端要送出的 request 是預期的,瀏覽器才會放行
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up