Web安全(一)---瀏覽器同源策略

Web安全(一) — 瀏覽器同源策略

#1 什麼是瀏覽器同源策略

瀏覽器的同源策略一直是開發中經常遇到的問題,它是瀏覽器最核心也是最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能都會受到影響

#1.1 什麼是同源 ?

同源是指同 協議同域名同端口

注:IE 未將端口號加入到同源策略的組成部分之中

在瀏覽器中, <script><img><iframe><link>等標籤都可以跨域加載,而不受瀏覽器的同源策略的限制, 這些帶src屬性的標籤每次加載的時候,實際上都是瀏覽器發起一次GET請求, 不同於普通請求(XMLHTTPRequest)的是,通過src屬性加載的資源,瀏覽器限制了JavaScript的權限,使其不能讀寫src加載返回的內容

瀏覽器同源策略中,除了上述的幾個標籤可以跨域加載外,其他出現跨域請求時,請求會發到跨域的服務器,並且會服務器會返回數據,只不過瀏覽器"拒收"返回的數據

#1.2 同源策略的限制

瀏覽器的同源策略目的是爲了保護用戶的信息安全,爲了防止惡意網站竊取用戶在瀏覽器上的數據,如果不是同源的站點,將不能進行如下操作 :

  • Cookie、LocalStorage 和 IndexDB 無法讀寫
  • DOM 和 Js對象無法獲得
  • AJAX請求不能發送

#1.2.1 不能讀寫Cookie、Session Storage、Local Storage、Cache、Indexed DB

用戶登錄某個站點,站點後端服務器驗證賬號密碼正確之後,會返回Cookie、Token 或者是用戶名和密碼給客戶端瀏覽器,瀏覽器會將這些個人數據保存到Cookie、Session Storage、Local Storage、Cache、Indexed DB其中的一個(具體怎麼保存,取決網站開發人員),如果瀏覽器沒有同源策略,當用戶訪問惡意網站時,惡意網站就可以通過腳本獲取用戶的數據,這是極其不安全的行爲

所以在不是同源的情況下,不能讀寫其他站點設置的Cookie、Session Storage、Local Storage、Cache、Indexed DB

#1.2.2 DOM

來自一個源的js只能讀寫自己源的DOM樹不能讀取其他源的DOM樹

#1.2.3 異步請求

一般而言來自一個源的js只能向自己源的接口發送請求,不能向其他源的接口發送請求。當然其實本質是,一方面瀏覽器發現一個源的js向其他源的接口發送請求時會自動帶上Origin頭標識來自的源,讓服務器能通過Origin判斷要不要嚮應;另一方面,瀏覽器在接收到響應後如果沒有發現Access-Control-Allow-Origin允許發送請求的域進行請求那也不允許解析

#2 跨域

不同域之間的訪問就叫跨域,因爲瀏覽器同源策略的限制,導致我們在不同源之間通信,出現了瀏覽器接受不到服務端返回數據的問題,這也是目前前後端分離的項目必須要解決的問題

#2.1 解決跨域的方法

  • 通過jsonp跨域
  • document.domain + iframe跨域
  • location.hash + iframe
  • window.name + iframe跨域
  • postMessage跨域
  • 跨域資源共享(CORS)
  • Nginx反向代理
  • nodejs中間件代理跨域
  • WebSocket協議跨域

下面主要講兩個平時我常用的解決跨域的方法 CORS 和 Nginx反向代理

#2.2 跨域資源共享(CORS)

只服務端設置Access-Control-Allow-Origin即可,前端無須設置,若要帶cookie請求:前後端都需要設置。

  • 服務端需要設置以下響應頭
Access-Control-Allow-Origin:http://www.admin.minhung.me // 一般用法(*,指定域,動態設置),*不允許攜帶認證頭和cookies 
Access-Control-Allow-Credentials: true  // 是否允許後續請求攜帶認證信息(:cookies),該值只能是true,否則不返回 
Access-Control-Max-Age: 1800 //預檢結果緩存時間,也就是上面說到的緩存,單位:秒 
Access-Control-Allow-Methods:GET,POST,PUT,POST // 允許的請求動詞, GET|POST|PUT|DELETE
Access-Control-Allow-Headers:x-requested-with,content-type //允許的請求頭字段

# CORS方法如何攜帶Cookie

如果使用CORS解決跨域問題,除了後端服務器需要配置以上信息外,前端也需要進行如下配置 :

// 表示跨域請求時是否需要使用憑證
axios.defaults.withCredentials = true // Vue.js框架

並且,後端服務器不能配置Access-Control-Allow-Origin: *,一定要記住,如果配置爲任意,不管withCredentials有沒有設置,cookie也帶不過去

#2.3 Nginx反向代理

通過nginx配置一個代理服務器(域名與端口號和客戶端不同)做跳板機,反向代理訪問api.minhung.me接口,並且可以順便修改cookie中admin.minhung.me信息,方便當前域cookie寫入,實現跨域登錄。

前端項目(admin.minhung.me:19700)

後端項目(api.minhung.me:19800)

在前端項目nginx配置中添加proxy_pass,將請求的接口代理到 api.minhung.me:19800

# 前端nginx配置 
server {
    listen       19700;
    server_name  admin.minhung.me;

    location / {
        proxy_pass   http://api.minhung.me:19800;  #反向代理
        proxy_cookie_domain api.minhung.me:19800 admin.minhung.me:19700; #修改cookie裏域名
        index  index.html index.htm;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章