你不知道的CORS跨域資源共享

瞭解下同源策略

  • 源(origin)*:就是協議、域名和端口號;
  • 同源: 就是源相同,即協議、域名和端口徹底相同
  • 同源策略:同源策略是瀏覽器的一個安全功能,不一樣源的客戶端腳本在沒有明確受權的狀況下,不能讀寫對方資源;
  • 同源策略的分類:node

    1. DOM 同源策略:即針對於DOM,禁止對不一樣源頁面的DOM進行操做;如不一樣域名的 iframe 是限制互相訪問。
    2. XMLHttpRequest 同源策略:禁止使用 XHR 對象向不一樣源的服務器地址發起 HTTP 請求。
  • 不受同源策略限制:ios

    1. 頁面中的連接,重定向以及表單提交(由於表單提交,數據提交到action域後,自己頁面就和其沒有關係了,不會管請求結果,後面操做都交給了action裏面的域)是不會受到同源策略限制的。
    2. 資源的引入不受限制,可是js不能讀寫加載的內容:如嵌入到頁面中的<script src="..."></script>,<img>,<link>,<iframe>

爲何要跨域限制

  • 若是沒有 DOM 同源策略:那麼就沒有啥xss的研究了,由於你的網站將不是你的網站,而是你們的,誰均可以寫個代碼操做你的網站界面
  • 若是沒有XMLHttpRequest 同源策略,那麼就能夠很輕易的進行CSRF(跨站請求僞造)攻擊:mongodb

    1. 用戶登陸了本身的網站頁面 a.com,cookie中添加了用戶標識。
    2. 用戶瀏覽了惡意頁面 b.com,執行了頁面中的惡意 AJAX 請求代碼。
    3. b.coma.com發起 AJAX HTTP 請求,請求會默認把 a.com對應cookie也同時發送過去。
    4. a.com從發送的 cookie 中提取用戶標識,驗證用戶無誤,response 中返回請求數據;數據就泄露了。並且因爲Ajax在後臺執行,這一過程用戶是沒法感知的。
  • (附)有了XMLHttpRequest 同源策略就能夠限制CSRF攻擊?別忘了還有不受同源策略的:表單提交和資源引入,(安全問題下期在研究)

跨域決解方案

  1. JSONP 跨域:借鑑於 script 標籤不受瀏覽器同源策略的影響,容許跨域引用資源;所以能夠經過動態建立 script 標籤,而後利用 src 屬性進行跨域;axios

    • 缺點:
    1. 全部網站均可以拿到數據,存在安全性問題,須要網站雙方商議基礎token的身份驗證。
    2. 只能是GET,不能POST。
    3. 可能被注入惡意代碼,篡改頁面內容,能夠採用字符串過濾來規避此問題。
  2. 服務器代理:瀏覽器有跨域限制,可是服務器不存在跨域問題,因此能夠由服務器請求所要域的資源再返回給客戶端。
  3. document.domain、window.name 、location.hash:藉助於iframe決解DOM同源策略
  4. postMessage:決解DOM同源策略,新方案
  5. CORS(跨域資源共享):這裏講的重點

CORS(跨域資源共享)

  • HTML5 提供的標準跨域解決方案,是一個由瀏覽器共同遵循的一套控制策略,經過HTTP的Header來進行交互;主要經過後端來設置CORS配置項。

CORS簡單使用

  • 以前說得CORS跨域,嗯嗯,後端設置Access-Control-Allow-Origin:*|[或具體的域名]就行了;
  • 第一次嘗試:
app.use(async(ctx,next) => {
    ctx.set({
        "Access-Control-Allow-Origin": "http://localhost:8088"
})
  • 發現有些請求能夠成功,可是有些仍是會報錯:

clipboard.png

  • 請求被同源策略阻止,預請求的響應沒有經過檢查:http返回的不是ok?
  • 而且發現發送的是OPTIONS請求:

clipboard.png

  • 發現:CORS規範將請求分爲兩種類型,一種是簡單請求,另一種是帶預檢的非簡單請求

簡單請求和非簡單請求

  • 瀏覽器發送跨域請求判斷方式:segmentfault

    • 瀏覽器在發送跨域請求的時候,會先判斷下是簡單請求仍是非簡單請求,若是是簡單請求,就先執行服務端程序,而後瀏覽器纔會判斷是否跨域;
    • 而對於非簡單請求,瀏覽器會在發送實際請求以前先發送一個OPTIONS的HTTP請求來判斷服務器是否能接受該跨域請求;若是不能接受的話,瀏覽器會直接阻止接下來實際請求的發生。
  • 什麼是簡單請求
  1. 請求方法是以下之一:後端

    • GET
    • HEAD
    • POST
  2. 全部的Header都只包含以下列表中(沒有自定義header):跨域

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma
  • 除此以外都是非簡單請求

CORS非簡單請求配置須知

  • 正如上圖報錯顯示,對於非簡單請求,瀏覽器會先發送options預檢,預檢經過後纔會發送真是的請求;
  • 發送options預檢請求將關於接下來的真實請求的信息給服務器:
Origin:請求的源域信息
Access-Control-Request-Method:接下來的請求類型,如POST、GET等
Access-Control-Request-Headers:接下來的請求中包含的用戶顯式設置的Header列表
  • 服務器端收到請求以後,會根據附帶的信息來判斷是否容許該跨域請求,經過Header返回信息:
Access-Control-Allow-Origin:容許跨域的Origin列表
Access-Control-Allow-Methods:容許跨域的方法列表
Access-Control-Allow-Headers:容許跨域的Header列表,防止遺漏Header,所以建議沒有特殊需求的狀況下設置爲*
Access-Control-Expose-Headers:容許暴露給JavaScript代碼的Header列表
Access-Control-Max-Age:最大的瀏覽器預檢請求緩存時間,單位爲s

CORS完整配置

  1. koa配置CORS跨域資源共享中間件:
const cors = (origin) => {
    return async (ctx, next) => {
        ctx.set({
            "Access-Control-Allow-Origin": origin, //容許的源
        })
        // 預檢請求
        if (ctx.request.method == "OPTIONS") {
            ctx.set({
                'Access-Control-Allow-Methods': 'OPTIONS,HEAD,DELETE,GET,PUT,POST', //支持跨域的方法
                'Access-Control-Allow-Headers': '*', //容許的頭
                'Access-Control-Max-Age':10000, // 預檢請求緩存時間
                // 若是服務器設置Access-Control-Allow-Credentials爲true,那麼就不能再設置Access-Control-Allow-Origin爲*,必須用具體的域名
                'Access-Control-Allow-Credentials':true // 跨域請求攜帶身份信息(Credential,例如Cookie或者HTTP認證信息)
            });
            ctx.send(null, '預檢請求')
        } else {
            // 真實請求
            await next()
        }
    }
}

export default cors
  • 如今不論是簡單請求仍是非簡單請求均可以跨域訪問啦~

跨域時如何處理cookie

  • cookie:瀏覽器

    • 咱們知道http時無狀態的,因此在維持用戶狀態時,咱們通常會使用cookie;
    • cookie每次同源請求都會攜帶;可是跨域時cookie是不會進行攜帶發送的;
  • 問題:緩存

    • 因爲cookie對於不一樣源是不能進行操做的;這就致使,服務器沒法進行cookie設置,瀏覽器也無法攜帶給服務器(場景:用戶登陸進行登陸操做後,發現響應中有set-cookie可是,瀏覽器cookie並無相應的cookie)
  • 決解:安全

    1. 瀏覽器請求設置withCredentials爲true便可讓該跨域請求攜帶 Cookie;使用axios配置axios.defaults.withCredentials = true
    2. 服務器設置Access-Control-Allow-Credentials=true容許跨域請求攜帶 Cookie
「積跬步、行千里」—— 持續更新中~,喜歡的話留下個贊和關注哦!
相關文章
相關標籤/搜索