跨域:跨域及解決方法

1、什麼是跨域

廣義的跨域包括:css

  1. 資源跳轉:超連接<a>跳轉、重定向、表單提交
  2. 資源嵌入:link、ifram、script、img,以及css樣式中的background:url()、@font-face()等外連接
  3. 腳本請求:js的ajax請求、js或DOM 中的跨域操做

狹義的跨域:指瀏覽器同源策略限制的請求html

注意:並非全部廣義的跨域操做都不被容許,只有被同源策略限制的跨域操做是不被容許的前端

 

2、什麼是瀏覽器同源限制

瀏覽器爲了安全考慮不容許訪問不一樣域下的資源html5

注意兩點:webpack

  1. 同源限制只是瀏覽器的安全策略,不是http協議的內容
  2. 對於向不一樣域下發起的請求,瀏覽器會照常發出,服務端處理後也會正常返回結果,但結果會在返回後被瀏覽器攔截

瀏覽器判斷同源的標準:nginx

  1. 請求協議相同
  2. 請求域名相同(包括父子域名都相同,特別注意:域名與對應IP不是同源
  3. 端口號相同

同源限制訪問那些內容:web

  1. cookie、LocalStorage、IndexDB等存儲信息沒法讀取
  2. DOM對象沒法獲取
  3. Ajax請求沒法完成

 

3、處理跨域的方法

一、JSONP

原理:使用<script>能夠跨域加載資源。瀏覽器端定義回調方法處理返回數據,跨域請求參數帶回調方法名;服務端須要返回方法名定義的方法,參數爲須要的數據,這樣瀏覽器接收後直接以數據爲參數調用回調方法ajax

// 瀏覽器端
function fn(data) {
   console.log('在這裏處理返回數據:' + data)
}
<script src="http://a.com/get-date?jsonp=fn"></script>

// 服務器端返回數據格式
fn({name: 'zhangs', age: 18})

優勢:沒有兼容性問題json

缺點:只支持get請求跨域

 

二、CORS

原理:在高版本的瀏覽器中,發現ajax請求跨域後會在請求頭部添加額外信息添加額外請求(預檢請求option),這樣只要服務端發現跨域請求後在返回頭部通知瀏覽器容許哪些站點跨域請求便可

過程:

  1. CORS在瀏覽器端代碼沒有任何區別,瀏覽器識別到跨域請求後自動對其進行處理,用戶沒有感知。
  2. 服務端處理後,在響應頭部添加Access-Control-Allow-Origin,指定容許請求的源
  3. 瀏覽器收到響應後根據Access-Control-Allow-Origin判斷本站點是否在容許範圍內,容許則接收數據繼續後續操做

肯定:兼容性不如jsonp(IE10以上支持)

優勢:基本知足http全部Method類型,也能夠指定部分支持Method

 

三、WebSocket

WebSocket是支持服務端與客戶端雙向通訊的應用層(與HTTP同層)協議,基於TCP協議。WebSocket在創建鏈接時須要藉助http,但鏈接創建後雙方通訊過程與http協議無關。

經過WebSocket與跨域服務創建鏈接,就能夠完成跨域請求

優勢:協議自定義,減小數據內容

肯定:主要用於雙向通訊的場景,不然長鏈接有必定的內存消耗

兼容性IE10以上,不過目前,對於低版本有必定的降級處理途徑,也有Socket.io可使用

 

四、postMessage

html5爲了解決不一樣源不能獲取DOM元素的問題,爲window對象添加了postMessage方法。

window.postMessage('這裏是要發送的信息', 'http://192.168.xxx.xx:3000/')

第一個參數:發送的內容

第二個參數:接收消息的源,包括協議類型、域名、端口號

 

五、nginx跨域處理

第一種:靜態資源添加Access-Control-Allow-Origin配置,原理同CORS(主要針對字體文件跨域請求,css、js等不受同源策略限制)

location / {
  add_header Access-Control-Allow-Origin *;
}

第二種:nginx反向代理解決跨域

實現思路:經過nginx配置一個代理服務器(域名與domain1相同,端口不一樣)作跳板機,反向代理訪問domain2接口,而且能夠順便修改cookie中domain信息,方便當前域cookie寫入,實現跨域登陸

#proxy服務器
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie裏域名
        index  index.html index.htm;

        # 當用webpack-dev-server等中間件代理接口訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啓用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #當前端只跨域不帶cookie時,可爲*
        add_header Access-Control-Allow-Credentials true;
    }
}

 參考文檔:

跨域幾種方式:https://juejin.im/post/5b04eae06fb9a07ac4806139

前端常見跨域解決方案(全):https://juejin.im/entry/59b8fb276fb9a00a42474a6f

相關文章
相關標籤/搜索