iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
自我挑戰組

菜鳥前端修練之旅系列 第 5

Day 05 | 同源政策(Same Origin Policy)

  • 分享至 

  • xImage
  •  

前端在串接 API 時很常會看到同源政策和 CORS 兩個詞,這篇來複習一下這兩個究竟是何物。

同源政策是什麼?

同源政策的全名為 Same Origin Policy。

當我們嘗試修改或讀取其他人的網站,會收到 blocked by CORS policy 的錯誤,因為瀏覽器會禁止跨域請求,這就是所謂的「同源政策」。

而同源政策又分成 DOM 同源政策Cookie 同源政策 兩種類型。

如何分辨是否同源?

只要 schemedomainport 三者相同,就會視為同源。

  • scheme(通訊協定,即為 http、https)。
  • domain(域名,例如 google.com)。
  • port(埠號,例如 :8000)。

如果以 https://example.com:8000 為例子來看的話:

http://example.com  // 不同源,scheme 不同
https://example.org // 不同源,domain 不同
http://example.com:3000  // 不同源,port 不同

學會分辨是否同源後,再回到 DOM 同源政策Cookie 同源政策 來看看。

DOM 同源政策

在瀏覽器中,圖片、影片、文字等資源在載入過後都會變成 DOM 元素,當我們試圖去載入其他網站的資源,會因為 DOM 同源政策而被阻止。

不過 DOM 同源政策 中,仍會有部分行為是被允許的,例如:

  • 跨來源的寫入: <form> 表單、連結、重新導向等。
  • 跨來源的嵌入: <img><audio><script> 等引入。

寫入及嵌入在一般情況下是被允許的,但是 跨來源讀取 通常不被允許,例如使用 XMLHttpRequestFetch 是會有問題的。也就是說當我們使用 JavaScript 進行跨來源的寫入、嵌入 、讀取的行為是有限制。

Cookie 同源政策

Cookie 同源政策DOM 同源政策 有些許不同。Cookie 同源政策 只要滿足 domain 和 path 相同就視為同源,scheme 的部分則需要額外設定。

除此之外,子網域及母網域的 Cookie 是可以共用的。

CORS(跨來源資源共用)

上面的文章有提到:JavaScript 進行跨來源的寫入、嵌入 、讀取的行為是有限制。雖然能防止惡意攻擊,但總有些情況是例外,例如我們需要串接第三方 API 等。

在 CORS 的規範中,跨來源請求分為兩種:簡單請求非簡單請求

簡單請求(simple requests)

簡單請求的條件有兩個:

  • HEADGETPOST 方法其中之一。
  • HTTP 的 header 限制為:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type 只能是 application/x-www-form-urlencoded、multipart/form-data、text/plain

非簡單請求

不符合上述兩個條件都列為非簡單請求,下例為 MDN 中的非簡單請求範例(Header 中帶了自定義的 X-PINGOTHER: pingpong):

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body);
    }
}

一旦瀏覽器發現這是非簡單請求,就會自動發出預檢請求(Preflight Request),預檢請求成功後,本身的請求才會發出。

問題回到如何解決 CORS 的問題:方法是在 server 端的 Access-Control-Allow-Origin 新增自己的網址,或設定為 *(全開),但全開的話還是有風險。

Access-Control-Allow-Origin: https://google.com
Access-Control-Allow-Origin: *  // 全開

或是只開部分 HTTP 方法,client 端認證:

Access-Control-Request-Method: POST
Access-Control-Allow-Credentials: true

參考資料


上一篇
Day 04 | Promise
下一篇
Day 06 | 加強 SCSS
系列文
菜鳥前端修練之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言