js -- 跨域問題
- 2022 年 5 月 9 日
- 筆記
- javascript
前言
出於瀏覽器同源策略的影響,瀏覽器會阻止一個域的 js 腳本和另一個域的內容進行交互,因此產生了跨域問題,該問題也經常在面試和開發中遇到,本文來總結一下相關知識點。
正文
1、什麼是同源策略
因為瀏覽器出於安全考慮,存在同源策略,就是說如果協議、域名、埠號有一個不同就產生了跨域,不同域之間的資源是不能交互的,比如:Ajax 請求別的域的資源就會失敗,無法讀取別的域中網頁的 Cookie 、LocalStorage 和 IndexedDB,無法獲取別的域中網頁中的 DOM 對象等。下面總結了跨域常見的解決方法。
2、跨域解決方法
(1)JSONP 解決跨域
JSONP 是伺服器與客戶端跨源通訊的常用方法。最大特點就是簡單適用,兼容性好(兼容低版本IE),缺點是只支援get請求,不支援post請求。
核心思想:網頁通過添加一個<script>元素,向伺服器請求 JSON 數據,伺服器收到請求後,將數據放在一個指定名字的回調函數的參數位置傳回來。
<script type="text/javascript">
// 創建jsonp 函數
function jsonp(url, data, callback) {
var id = "_" + "Json" + (new Date()).getTime(); //創建一個幾乎唯一的id
window[id] = function (result) {
if (callback) {
callback(result);
}
var getId = document.getElementById(id); //移除Script標籤和id
getId.parentNode.removeChild(getId);
window[getId] = null; //調用函數後進行銷毀
}
url = url.replace("callback=?", "callback=" + id);
const script = document.createElement('script')
script.src = url
script.id = id
script.async = true
script.type = 'text/javascript'
document.body.appendChild(script)
}
// 創建回調函數
function dosomething(res) {
console.log(res.data)
}
// 調用jsonp函數
jsonp('//test.com/api/getInfo?callback=?', dosomething)
</script>
(2)document.domain 解決跨域
瀏覽器通過 document.domain 屬性來判斷兩個頁面是否同源,因此可以設置相同的 document.domain 屬性值來解決跨域,缺點該方法只限於主域相同,子域不同的跨域場景。
// a.html document.domain = "test.com" // b.html document.domain = "test.com"
(3)postMessage Api 解決跨域
通常用於獲取嵌入頁面中的第三方數據,一個頁面發送消息,另一個頁面接收消息,比如通過 iframe 標籤嵌入的父子頁面之間的消息傳值。
<!-- 父頁面 --> <iframe src="child.html" frameborder="0" id="Iframe"></iframe> <script> // 監聽子頁面傳遞的值 window.addEventListener('message', function (event) { }) // 給子頁面發消息 document.getElementById('Iframe').contentWindow.postMessage(message, "*") </script> <!-- 子頁面 --> <script> // 子頁面給父頁面發消息 window.parent.postMessage("給父頁面發消息", '*') // 監聽父頁面的消息 window.addEventListener('message', function (event) { }) </script>
(4)CORS 解決跨域
該方式需要服務端和瀏覽器同時支援,瀏覽器會自動進行 CORS 通訊,後端實現了 CORS 就實現了跨域,服務端需要設置 Access-Control-Allow-Origin 就可以開啟 CORS ,該屬性表示哪些域名可以訪問資源,如果使用通配符則表示所有網站都可以訪問。
如果要實現帶 Cookie 進行跨域請求,前端需要額外設置 withCredentials 為 true。
(5)Nginx 反向代理
該方法需要通過 Nginx 搭建中轉伺服器,用於轉發請求。只需要在 nginx.config 中配置轉發請求即可。
(6)webpack-dev-server 設置本地代理
該方式用於開發環境中,在webpack.config.js 中設置代理的本地伺服器就可以,如下:
devServer: { port: 8080, proxy: { "/api": { target: "//192.168.25.20:8088" // 後端介面 } } }
寫在最後
以上就是本文的全部內容,希望給讀者帶來些許的幫助和進步,方便的話點個關注,小白的成長之路會持續更新一些工作中常見的問題和技術點。


