web跨域及cookie相關知識總結

煩囂的人發表於2019-06-24

  之前對於跨域相關的知識一致都很零碎,正好現在的程式碼中用到了跨域相關的,現在來對這些知識做一個彙總整理,方便自己檢視,說不定也可能對你有所幫助。

本篇主要內容如下:

  • 瀏覽器同源策略
  • http 請求跨域
  • http 請求跨域解決辦法
  • cookie 機制
  • 如何共享 cookie

瀏覽器同源策略

  相信很多人在 web 入門時,都被跨域問題折磨的死去活來。要想完全掌握跨域就得知道為什麼會有跨域這個問題出現。

  簡單來說跨域問題是因為瀏覽器的同源策略導致的。那瀏覽器為什麼要有同源策略呢?

  當然是為了安全。沒有同源策略限制的瀏覽器環境是非常危險的(即使有了同源策略也不是百分百安全),有興趣的可以去了解了解CSRFXSS攻擊。

  所謂的“同源”指的是“三個相同”:

  • 協議相同。不能一個是 http 協議,一個是 https
  • 域名相同
  • 埠相同

如果非同源頁面有以下限制:

  • LocalStore 和 IndexDB 無法讀取。這兩個顯然是不能讀取的,但是 cookie 有點不一樣,放在後面單獨說明
  • DOM 無法獲取,比如如法在頁面 A 中通過 iframe 獲取異源頁面 B 的 DOM
  • AJAX 請求無法讀取(可以傳送請求,但是無法讀取到請求結果。比如在頁面 A 中請求異源介面 B,請求會正常發出處理,但是在頁面 A 中無法獲取請求結果,除非響應頭 Access-Control-Allow-Headers 中允許了頁面 A 的源,這樣就能讀取到結果)

  但是這裡有個例外,所有帶“src”屬性的標籤都可以跨域載入資源,不受同源策略的限制,這樣你應該可以想到一個比較古老的跨域解決方案(JSONP),同時這個特性也會被用作 CSRF 攻擊。

http 請求跨域

  在前端開發中經常會遇到跨域的問題,比如前後端分離中前後端部署在不同的埠上,或者在前端頁面中需要向另外一個服務請求資料,這些都會被跨域所阻擋。

目前主要有以下幾種辦法解決跨域問題:

  1. 關閉瀏覽器同源檢查

  這個太暴力,也太不安全了,不用考慮。

  1. jsonp 實現跨域請求

  前面說過了瀏覽器對於帶 src 屬性的標籤都可以跨域的。因此 jsonp 的實現流失利用了這個特性,在頁面中動態插入一個<script>標籤,然後他的 src 屬性就是介面呼叫地址,這樣就能訪問過去了,然後再講返回內容特殊處理成立即執行的函式,這樣就看起像進行了一次跨域請求。之所以不推薦這種方式,主要有以下兩個原因:

  • 實現複雜,且需要前後臺同時修改才能實現
  • 只能進行 get 請求
  1. 伺服器設定執行跨域

  這種方法只需要後臺做處理便能實現跨域,前面說的 http 跨域請求是能夠發出去的,只是不能接收,那我們只要在響應頭Access-Control-Allow-Headers中加入允許請求的地址即可,以,分隔,同時*代表所有地址都允許。比如:

Access-Control-Allow-Headers:http://localhost:8081,http://localhost:8082

本方法是較為常用的一中跨域辦法,只需簡單修改服務端程式碼即可。

  1. 請求代理

  這也是非常常用的一種跨域方法。跨域限制只是瀏覽器限制,服務端並沒有這個概念,因此我們在前端還是請求同域地址,然後在服務端做一個代理,將請求轉發到真正的 ip 和埠上。通常使用 nginx 實現埠轉發,比如下面一段 nginx 配置:

server {
    # /test1/abc 轉發到 http://a.com:8011/abc
    location /test1/ {
        proxy_pass http://a.com:8011/;
    }

    # /test2/abc 轉發到 http://b.com:8011/main/abc
    location /test2/ {
        proxy_pass http://b.com:8011/main/;
    }

    # /test3/abc 轉發到 http://c.com:8011/test3/abc
    location /test3/ {
        proxy_pass http://c.com:8081;
    }
}

cookie 同源策略

  cookie 的同源策略是通過
web跨域及cookie相關知識總結
Domainpath兩個部分來共同確認一個 cookie 在哪些頁面上可用。

  Domain確定這個 cookie 所屬的域名,不能帶埠或協議。因此 cookie 便可在不同埠/不同協議下共享,只要域名相同。有一個例外是父子域名間也能共享 cookie,只需將 Domain 設定為.父域名

  path就簡單多了,通過 Domain 確定哪些域名可以共享 cookie,然後在通過path來確定 cookie 在哪些路徑下可用。使用/表示所有路徑都可共享。

具體如下:

注意:在跨域請求中,即時目標地址有 cookie 且發起請求的頁面也能讀取到該 cookie,瀏覽器也不會將 cookie 自動設定到該跨域請求中。比如在http://localhost:8082/a頁面中請求http://localhost:8081/abc,這兩個地址下擁有共享cookie,http請求也不會攜帶cookie。

本篇原創釋出於:FleyX 的個人部落格

相關文章