iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 10
0
自我挑戰組

前端菜焦阿日記系列 第 10

|D10| Web Server - 跨域請求

tags: 2019年鐵人賽web-server

在接別人API時會出現這個錯誤回應,是因為瀏覽器基於同源政策的規範,有一些對請求的限制。

同源政策

同源政策出發點是為了防止CSRF誇站請求偽造的惡意攻擊,所以發出請求的來源要遵守以下三點

  • 相同協議(protocol)
  • 相同網域(domain)
  • 相同端口(port)

同源政策限制了程式碼和不同 domain 的資料傳送,不同源會被擋下來

那怎麼串接成功?

CORS

幾乎不太可能跟要接的 API 在同一 domain 下,所以為了讓不同源之間可以傳輸資料,又有另外一個規範叫 CORS。

CORS規範說,如果想開啟跨來源 HTTP 請求的話,Server 必須在 Response 的 Header 裡面加上 Access-Control-Allow-Origin 的設定。

錯誤回應裡有提到

設定成功在Devtools會看到

Access-Control-Allow-Origin: *表示允許任何來源

另外,也可以定義接受哪些請求的 Header 或 Method Access-Control-Allow-HeadersAccess-Control-Allow-Methods

預檢(preflight)請求

成功接上API後,會發現我們只有發送一個 POST 請求,但怎麼先傳了 OPTIONS ?

CORS把請求分為兩種,簡單請求預檢(preflight)請求

  • 簡單請求
    要滿足所有判斷條件,最容易分辨的是沒有自定義 Header,而且又是 GET 。

    //範例
    GET https://api.users.com/user/1 HTTP/1.1
    
  • 預檢(preflight)請求

    //範例
    var xhr = new XMLHttpRequest()
    xhr.open("POST","http://api") //用post方法發請求到api網址
      xhr.addEventListener('readystatechange', function(e) {
        if (e.target.readyState === 4 && e.target.status === 200) {
          //....
    
        } else if (e.target.readyState === 4) {
          //....
        }
      });
      xhr.setRequestHeader("Content-Type", "application/json");
      xhr.send();
    

    因為不是簡單請求,所以瀏覽器會先送出 HTTP 的 OPTIONS 方法,確認 Server 的 Response 是否有 Access- Control-Allow-Origin ,確認有之後才會把我們的請求送出。

  • How CORS works

    圖片來源:wikipedia

小測驗

http://test.you.com/dir/page.html
表格都是和以上這一個URL比較

URL 比較結果 原因
http://test.you.com/watch/page.html 同源
http://test.you.com:87/dir/page.html 不同源 不同 port
https://test.you.com/dir/page.html 不同源 不同協議
http://fined.you.com/dir/page.html 不同源 不同 domain

參考來源


上一篇
|D9| Web Server - 解剖URL
下一篇
|D11| CSS - 文字和inline垂直置中
系列文
前端菜焦阿日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
Arel
iT邦新手 5 級 ‧ 2018-10-25 20:19:08

芒果博士

0
Chris
iT邦新手 4 級 ‧ 2018-10-25 22:01:06

這篇真棒

0
turtle0617
iT邦新手 5 級 ‧ 2018-10-26 09:22:57

芒果博士!

我要留言

立即登入留言