同源策略及跨域的解決方案

同源策略的基本概念

同源策略簡介:1995年,同源政策由Netscape引入瀏覽器,目前,全部的瀏覽器都實行這個政策.javascript

同源:指的是協議,域名,端口號相同都稱爲是同源網站css

同源策略的目的html

同源策略的目的,是爲了保證用戶信息的安全,防止惡意的網站竊取數據前端

同源策略的限制範圍html5

隨着互聯網的發展,'同源策略'愈來愈嚴格,目前,若是非同源,下面的行爲將會受到限制:java

  1. Cookie、LocalStorage 和 IndexDB 沒法讀取。
  2. DOM 沒法得到。
  3. AJAX 請求在瀏覽器端有跨域限制

雖然這些限制是保證了數據的安全性,可是同時他也給開發者帶來了必定的困擾,因爲網絡的不斷髮展,不一樣公司的業務更加龐大,所須要的技術也更加精準,因此各個部門都會有本身的域名,這時就會出現跨域現象ajax

解決跨域的方案

方法一JSONP:json

JSONP(JSON with Padding)、可用於解決主流瀏覽器的跨域數據訪問的問題。後端

因爲DOM中的src屬性支持跨域,因此JSONP的原理也就是利用了script標籤中的src來實現跨域的,除了script標籤以外,還有img和link標籤.api

<!--不受同源策略限制的標籤-->
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">
<script src="http://www.api.com/1.js"></script>
複製代碼

JSONP實現代碼

<script> var inp = document.getElementById('inp'); var ul = document.querySelector('ul'); function suggest_so(data){ // console.log(data) ul.innerHTML ='' var {result} = data; result.forEach(function(ele){ var li = document.createElement('li'); li.innerHTML = ele.word; ul.appendChild(li) }) } inp.oninput = function(){ if(document.getElementsByClassName('ss').length>0){ document.getElementsByClassName('ss')[0].remove() } var val = inp.value; // 經過動態建立src屬性實現 var jsonp = document.createElement('script'); jsonp.src = 'https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word='+val; jsonp.className = 'ss'; document.body.appendChild(jsonp) } </script>

複製代碼

在script屬性中有一個src屬性,裏面有一個callback回調函數,這個回調函數是在src裏面的,他的做用就是當響應來到時,應該在頁面中調用的函數,而數據就是傳入回調函數的JSON數據.

JSONP實現原理

  • 1)利用了script的src屬性支持跨域訪問
  • 2)script標籤的後面須要寫上須要請求的頁面,發送了一個方法的名字到服務器.
  • 3)服務器接收到名字以後,拼接一個方法的調用在參數中傳入須要給瀏覽器的數據
  • 4)返回瀏覽器,瀏覽器把他們當js解析,沒有跨域問題,從服務器獲取數據
原理:服務端返回一個定義好的js函數的調用,而且將服務器的數據以該函數參數的形式傳遞過來,這個方法須要先後端配合.
複製代碼

jQuery實現跨域

$(function(){
  $('#inp').on('input',function(){
    $.ajax({
      url:'https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word='+$(this).val(),
      dataType:'jsonp',
      jsonpCallback:'suggest_so',
      success:function(data){
        var {result} = data;
        var str = template('tpl',{result});
        $('ul').html(str)
      }
    })
  })
})
複製代碼

這裏用的是dataType和jsonpCallback,來實現跨域

JSONP的缺點:

  • 1它只支持GET請求而不支持POST等其它類型的HTTP請求
  • 2它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JavaScript調用的問題。
  • 3 jsonp在調用失敗的時候不會返回各類HTTP狀態碼。
  • 4缺點是安全性。萬一假如提供jsonp的服務存在頁面注入漏洞,即它返回的javascript的內容被人控制的。那麼結果是什麼?全部調用這個 jsonp的網站都會存在漏洞。因而沒法把危險控制在一個域名下…因此在使用jsonp的時候必需要保證使用的jsonp服務必須是安全可信的。

只支持get請求的緣由:

因爲script標籤只能發送get請求 因此jsonp不支持post方式的跨域

方法二CORS: 具體流程: 瀏覽器發送跨域請求

服務器端收到一個跨域請求後,在響應頭中添加Access-Control-Allow-Origin Header資源權限配置。發送響應

瀏覽器收到響應後,查看是否設置了header('Access-Control-Allow-Origin:請求源域名或者*');

若是當前域已經獲得受權,則將結果返回給JavaScript。不然瀏覽器忽略這次響應。

app.get('/getmsg',(req,res)=>{
    let msg =[{name:'zs',age:18,gender:'boy'}];
    res.header('Access-Control-Allow-Origin',"*")
    res.json({msg:'ok',code:200,data:msg})
})
複製代碼

這種方法雖然簡單,可是這種方法是h5新出的,因此這種方法有兼容性問題

方法三Nginx:

同源策略只是針對的瀏覽器端,因此這裏經過服務端反向代理的方式實現跨域, Nginx解決跨域問題經過Nginx反向代理將對真實服務器的請求轉移到本機服務器來避免瀏覽器的"同源策略限制"。

方法四:

window.name+iframe 須要目標服務器響應window.name。

方法五:

window.location.hash+iframe 一樣須要目標服務器做處理。

方法六:

html5的 postMessage+ifrme 這個也是須要目標服務器或者說是目標頁面寫一個postMessage,主要側重於前端通信。

HTML5爲了解決這個問題,引入了一個全新的API:跨文檔通訊 API(Cross-document messaging)。

這個API爲window對象新增了一個window.postMessage方法,容許跨窗口通訊,不論這兩個窗口是否同源。

舉例來講,父窗口http://aaa.com向子窗口http://bbb.com發消息,調用postMessage方法就能夠了。

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
複製代碼

postMessage方法的第一個參數是具體的信息內容,第二個參數是接收消息的窗口的源(origin),即"協議 + 域名 + 端口"。也能夠設爲*,表示不限制域名,向全部窗口發送。

子窗口向父窗口發送消息的寫法相似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');
複製代碼

方法七:

Cookie 是服務器寫入瀏覽器的一小段信息,只有同源的網頁才能共享。可是,兩個網頁一級域名相同,只是二級域名不一樣,瀏覽器容許經過設置document.domain共享 Cookie。

舉例來講,A網頁是http://w1.example.com/a.html,B網頁是http://w2.example.com/b.html,那麼只要設置相同的document.domain,兩個網頁就能夠共享Cookie。

document.domain = 'example.com';
複製代碼

如今,A網頁經過腳本設置一個 Cookie。

document.cookie = "test1=hello";
複製代碼

B網頁就能夠讀到這個 Cookie。

var allCookie = document.cookie;
複製代碼

注意,這種方法只適用於 Cookie 和 iframe 窗口,LocalStorage 和 IndexDB 沒法經過這種方法,規避同源政策,

相關文章
相關標籤/搜索