同源策略和CORS

github連接html

同源策略

從一個問題開始:node

爲何表單提交沒有跨域問題,但ajax提交有跨域問題?git

例子github

若是咱們向百度發起POST請求,會發現302失敗了,不容許發POST請求。可是,若是發起Get請求,發現200成功了,記得點一下Preserve log , 在頁面刷新和頁面切換期間,勾選 ‘Preserve log’選項(在控制檯上方)會保留控制檯歷史信息。除非你清除console或者關閉tab,不然信息將一直保留。也就是說,用表單向百度發起一個Get請求是沒有任何問題的!!!雖然是2個不一樣的域名!!!!面試

一樣的請求若是用Ajax作一遍:ajax

雖然也是200成功了,可是log控制檯卻拋出一個錯誤:加載baidu.com失敗了,是由於響應裏面沒有一個叫Access-Control-Allow-Origin的header所以不容許。理論上既然已經請求成功了,就因該響應一個html即百度的首頁,可是響應是空白狀態碼是0是怎麼回事?後端

這就是同源策略,若是不是baidu.com裏的JS,就不能向baidu.com的域名發起Ajax請求api

只有協議+端口+域名 如出一轍才容許發Ajax請求(也就是讓js調用XMLHttpRequest發起請求)跨域

如出一轍如出一轍如出一轍如出一轍如出一轍如出一轍如出一轍如出一轍如出一轍如出一轍瀏覽器

1.http://baidu.com能夠向http://www,baidu.com發Ajax請求嗎? yes/no 答案是:No

2.http:baidu.com:80能夠向http://baidu.com:81發Ajax請求碼? yes/no 答案是 No

www.baidu.com 和 baidu.com多是2個徹底不一樣的網站,因此瀏覽器不能認爲冒險,全部不容許在baidu.com裏向www.baidu.com發Ajax請求

爲何要用同源策略?

由於若是用form表單提交頁面會刷新,以前的頁面就會掛掉,掛掉的頁面死無法拿到新的頁面的內容的,因此瀏覽器會認爲這是安全的。(只有aJax發的請求會受到同源策略的限制) 可是Ajax是能夠讀取響應內容的,由於瀏覽器是不少人在使用,若是容許讀取別人的內容,若是能夠訪問支付寶的APi,是否是能夠用Ajax發GEt請求首頁的html,去找html裏的餘額讀取別人的支付寶餘額,用戶毫無隱私可言,甚至能夠訪問QQ空間的照片留言等,因此瀏覽器必定要作一個安全限制,若是沒有同源策略,就能夠直接發起Get或者直接POST請求(能夠POST能夠直接轉帳)

瀏覽器必須保證:只有協議+端口+域名如出一轍才容許發Ajax請求(也就是讓js調用XMLHttpRequest發起請求),不然他就是一個很是危險的瀏覽器,形成隱私的泄露,這也是物聯網的基礎

若是實在是想請求那個域名呢?你能夠和那個域名的後臺打個電話,好比A是Tom.com的開發,B是Jack.com的開發,A想用AjaxGetB的內容,A就打電話對B說,讓B告訴瀏覽器容許A去訪問B,就能夠了,那該怎麼去實現呢?

在main.js裏請求request.open('Get', 'http://jack.com:8002/xxx')

同時開啓2個服務:node server.js 8001node server.js 8002

在瀏覽器裏新開2個窗口:http://tom.com:8001http://jack.com:8002/

咱們會發如今tom的窗口裏得不到請求的響應,由於不一樣協議端口域名網站之間不容許發起Ajax請求,這也是同源策略的內容

Access to XMLHttpRequest at 'http://jack.com:8002/xxx' from origin 'http://tom.com:8001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
複製代碼

在jack的窗口裏發起的請求獲得了響應

這時候tom同窗就會打電話給jack同窗,我要訪問你的域名下的一個api叫/xxx(/xxx路徑),有2中解決問題的辦法

第一種是J經過SONP的方法(JSONP存在一個問題,因爲JSONP是經過動態建立script來發請求的,因此它只能發Get請求不能發POST請求)

第二種是經過CORS的方法(通常用CORS的方法來解決跨域訪問受同源策略限制)

CORS

CORS的全拼是Cross-origin resource sharing即「跨站資源共享」

CORS能夠告訴瀏覽器,我倆一家的,別阻止他

Jack只須要在後端代碼(server.js)加一句響應頭:

response.setHeader('Access-Control-Allow-Origin',' http://tom.com:8001')
複製代碼

若是把這裏的http://tom.com:8001網址改成 * 號,就表示容許全部網站去訪問

意思是:容許http://tom.com:8001這個域名get http://jack.com:8002/

這時候重啓服務器以後,在tom的頁面經過點擊按鈕向jack的網站發起一個get請求就會獲得響應了,不會再受同源策略的限制了!!


總結

1.若是面試讓手寫Ajax。則

let request = new XMLHttpRequest()                      // 建立XMLHttpRequest對象
    request.open('Get', 'http://jack.com:8002/xxx')     //初始化它,配置request
    request.send()                                      // 發送它
    request.onreadystatechange = function () {          // 監聽onreadystatechange
        if (request.readyState === 4) {                 //  判斷readyState
            if (request.status >= 200 && request.status < 300) {// 判斷request.status
                let string = request.responseText
                let obj = window.JSON.parse(string)
            } else if (request.status >= 400) {
                console.log('請求失敗了')
            }
        }
    }
複製代碼

2.用JS發起請求,再用jS處理響應就是Ajax

3.把XML進化成了JSON,JSOn是一個新的語言吧,它只支持JS的一部分語法,由於它抄襲了JS

4.Ajax有一個優勢就是安全,由於它有同源策略。同源策略的內容是隻有協議+端口+域名 如出一轍才容許發Ajax請求,若是不同,即便能發送成功可是拿不到響應的結果

5.若是向突破同源策略,該如何跨域呢?

突破同源策略 === 跨域 ===OCRS,CORS的內容就是告訴瀏覽器「他是我兄弟別阻止他去讀取個人內容」,只須要在須要被訪問的網站的後端加上一句話:

response.setHeader('Access-Control-Allow-Origin',' http://tom.com:8001')
複製代碼
相關文章
相關標籤/搜索