前言 自動接觸前端,跨域這個詞就一直縈繞在耳畔。因為一般接手的項目都已經做好了這方面的處理,而且之前一直感覺對這方面模棱兩可,所以今天就抽個時間梳理一下。 為什么需要跨域 跨域這個概念來自一個叫 “同源策略” 的東西。同源策略是瀏覽器(注意是瀏覽器,跟通信協議無關)上為了安全考慮實施的非常重要的安全機制。 Ajax 默認只能獲取到同源的數據,對于非同源的數據,Ajax是獲取不到的。 什么是同源? 協議相同 域名相同 端口相同 舉例來說,http://www.example.com/dir/page.html這個網址,協議是http://,域名是www.example.com,端口是80(默認端口可以省略)。這個網址,在這個地址中要去訪問下面服務器的數據,那么會發生什么情況呢? URL 結果 原因 //www.example.com/dir/other.html 不同源 協議不同,https 和 http http://en.example.com/dir/other.html 不同源 域名不同 http://www.example.com:81/dir/other.html 不同源 端口不同 http://www.example.com/dir/page2.html 同源 協議,域名,端口都相同 http://www.example.com/dir2/page.html 同源 協議,域名,端口都相同 那么。想要獲取非同源地址的數據,就要使用跨域。不論是 Ajax 還是跨域,都是為了訪問服務器的數據。簡單的來說, Ajax 是為了訪問自己服務器的數據,跨域是為了訪問別人服務器的數據(比如獲取天氣信息,航班信息等)。 同源策略的目的 為了保證用戶信息的安全,防止惡意的網站竊取數據。 “ 設想這樣一種情況:A網站是一家銀行,用戶登錄以后,又去瀏覽其他網站。如果其他網站可以讀取A網站的 Cookie,會發生什么? 很顯然,如果 Cookie 包含隱私(比如存款總額),這些信息就會泄漏。更可怕的是,Cookie 往往用來保存用戶的登錄狀態,如果用戶沒有退出登錄,其他網站就可以冒充用戶,為所欲為。因為瀏覽器同時還規定,提交表單不受同源政策的限制。 由此可見,"同源政策"是必需的,否則 Cookie 可以共享,互聯網就毫無安全可言了?!?via@ 阮一峰 實現跨域的方式 反向代理 JSONP WebSocket CORS(根本解決方案) 反向代理 反向代理就是使用自己的服務器,在后端請求目標服務器的數據,然后返回給客戶端。相當于做了一把中間人的感覺。 反向代理服務器,最常用的就是Nginx。但是作為前端代碼實現的Node.js也可以搭建反向代理服務器。 下面來簡要介紹使用node服務進行反向代理。 要實現這個前提是,前端開發環境必須運行在nodejs服務中,所幸的是,現在前端的開發自動化工具都是建立在nodejs上的,所以這個前提也不是很重要。 比如我有一個后端接口:http://39.105.136.190:3000/zhuiszhu/goods/getList,可以獲取一些商品列表數據,但是我運行的node項目是在 localhost:3000 下的,明顯構成跨域。 我們根據項目使用的框架不同,處理的方式也不同。 1、nodejs+express+http-proxy-middleware 插件代理 如果是express項目,可以使用http-proxy-middleware 來處理,這個插件主要用于將前端請求代理到其它服務器。 用法很簡單。你可以參考插件github官網: //github.com/chimurai/http-proxy-middleware 首先需要在你的express項目中安裝該插件: npm install --save-dev http-proxy-middleware 然后在 app.js 中進行代理設置(示例如下): var express = require('express'); var proxy = require('http-proxy-middleware'); var app = express(); app.use('/zhuiszhu', proxy({target: 'http://39.105.136.190:3000/', changeOrigin: true})); app.listen(3000); 之后再項目中再次發送ajax請求的時候,可以看到數據可以收到了。 $.ajax({ url: '/zhuiszhu/goods/getList', type: 'GET', success(res) {}, }); 2、webpack-dev-server 代理 我們經常在vue開發項目的時候,會用webpack作為前端自動化構建工具的話,也會使用到webpack-dev-server的插件,那么可以引用webpack-dev-server來進行配置跨域方案。 webpack-dev-server是一個小型的nodejs服務器,是基于express框架的,用于實時監聽和打包編譯靜態資源。其中里面有一個屬性是proxy,是專門來配置代理請求接口的。 你只需要在webpack.config.js中 devServer中如下設置即可: devServer: { port: 3000, inline: true, proxy: { "/zhuiszhu": { target: "http://39.105.136.190:3000/", changeOrigin: true //必須配置為true,才能正確代理 } } }, 其實可以看出, webpack 的 devServer.proxy 就是使用了非常強大的 http-proxy-middleware 包來實現代理的,所以本質上是相通的。 JSONP JSONP基本思想是,網頁通過添加一個<script>元素,向服務器請求JSON數據,這種做法不受同源政策限制;服務器收到請求后,將數據作為參數放在一個指定名字的回調函數里傳回來,這個回調函數的名字我們需要通過js定義好。 比如:當頁面資源加載完畢時候,獲取跨域的數據,并且制定回調函數的名字為foo: window.onload = function () { var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.src = "http://bbb.com?callback=foo; document.body.appendChild(script); }; foo(data) { console.log(data); // data即為跨域獲取到的數據 } 在服務器那邊,需要將數據放入foo函數的參數中: foo('hello world') 使用JSONP需要注意: 必須后端配置相應回調函數。 只能發送GET請求。 WebSocket WebSocket是一種通信協議,使用ws://(非加密)和wss://(加密)作為協議前綴。該協議不實行同源政策,只要服務器支持,就可以通過它進行跨源通信。 由于發出的WebSocket請求中有有一個字段是Origin,表示該請求的請求源(origin),即發自哪個域名。 正是因為有了Origin這個字段,所以WebSocket才沒有實行同源政策。因為服務器可以根據這個字段,判斷是否許可本次通信。 CORS CORS全稱“ Cross-origin resource sharing ”(跨域資源共享),相比JSONP, CORS允許任何類型的請求 。 CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。 整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。 因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。 總結 綜上,如果訪問的別人服務器的資源,并且未設置JSONP,也未開放WebSocket白名單,也沒有設置CORS接口,那么唯一的選擇就是使用自己的服務器進行反向代理。 參考鏈接 瀏覽器同源政策及其規避方法 跨域資源共享 CORS 詳解 express框架介紹 http-proxy-middleware 本文完。 (啾咪 ^.<)
轉載自://www.cnblogs.com/lvonve/p/11811856.html
欧美黄色网