本菜雞最近在寫某個頁面請求資料時,報瞭如下的錯誤。
Failed to load https://...: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:7070' is therefore not allowed access.
瞭解原因後,得知是由於跨域請求導致的,學習了一下跨域及同源策略相關知識後,寫了個demo玩玩
簡單聊聊跨域
要了解跨域,必須先了解瀏覽器同源策略,接下來搬運了一些大神的總結
什麼是同源策略?
同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協議+域名+埠"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
同源策略限制以下幾種行為:
1.Cookie、LocalStorage 和 IndexDB 無法讀取
2.DOM 和 Js物件無法獲得
3.AJAX 請求不能傳送
複製程式碼
假設沒有同源策略,那麼我在A網站下的cookie就可以被任何一個網站拿到;那麼這個網站的所有者,就可以使用我的cookie(也就是我的身份)在A網站下進行操作。同源策略可以算是 web 前端安全的基石,如果缺少同源策略,瀏覽器也就沒有了安全性可言。
同源策略做了很嚴格的限制,但是在實際的場景中,又確實有很多地方需要突破同源策略的限制,也就是我們常說的跨域。 跨域的方法有很多(如接下來要玩的jsonp跨域,還有cors跨域資源共享,反向代理等等)。
使用jsonp跨域
由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而HTML的<script>
元素是一個例外。利用<script>
元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。
示例程式碼
function handleResponse(response) {
alert(`You get the data : ${response}`)
}
const script = document.createElement('script')
script.src = 'http://somesite.com/json/?callback=handleResponse'
document.body.insertBefore(script, document.body.firstChild)
複製程式碼
這裡的callback回撥函式很重要,動態新增在body中的script標籤可以使用被載入的檔案與HTML檔案下的其他JS檔案共享一個全域性作用域。也就是說,<scritp>標籤載入到的資源是可以被全域性作用域下的函式所使用的!
玩一玩,寫一個百度搜尋框
百度有一個對外暴露的資料介面:sp0.baidu.com/5a1Fazu8AA5…
在chrome瀏覽器中開啟百度主頁,在開發者工具在 netkwork 可以找到
我們可以直接拿來使用,配合jsonp就能實現跨域獲取輸入框內容相關熱點資料並點選跳轉了,具體實現請看Github專案原始碼實現效果:
頁面結構非常簡單,如圖:jsonp跨域實現程式碼
document.onkeyup = function () {
var val = text.value
var script = document.createElement('script')
script.src = `https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${val}&cb=dosomething`;
document.body.appendChild(script)
}
function dosomething (data) {
var oUl = document.querySelector('#lists ul')
oUl.innerHTML = ''
data.s.map(function (html) {
var oLi = document.createElement('li')
oLi.innerHTML = html
oLi.onclick = function () {
window.location.href = `http://www.baidu.com/s?wd=${html}`
}
oUl.appendChild(oLi)
})
}
複製程式碼
僅僅是一個利用jsonp實現跨域的簡單小demo,便於和我一樣的新手學習,其它結構和樣式檔案就不一一列出來了,可以到我下載我的完整專案檢視 完整專案地址:Github:baidu_demo
參考文章: