1. 程式人生 > >JS中的跨域問題

JS中的跨域問題

ole 銀行 cors 情況 響應 control dos 訪問出錯 ont

跨域訪問出錯信息:No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. Origin ‘http://localhost:9100‘ is therefore not allowed access. The response had HTTP status code 400.

1、跨域的概念

跨域是指從一個域名的網頁去請求另一個域名的資源。比如從www.baidu.com 頁面去請求 www.google.com 的資源。由於瀏覽器的同源策略跨域訪問會受到限制。同源策略指的是域名、協議、端口號都相同,只要 協議,域名,端口有任何一個的不同,就被當作是跨域。

URL由協議+主機名/域名+端口+路徑+查詢字符串+信息片段組成。

技術分享圖片

http://mail.163.com:8000/index.html
http://:是協議;mail:是服務器名;163.com:是域名;mail.163.com:這個是主機名(網站名),由服務器名+域名組成;8000:是端口號

1.1、限制跨域訪問的原因

安全問題:如果一個網頁可以隨意地訪問另外一個網站的資源,那麽就有可能在客戶完全不知情的情況下出現安全問題。比如用戶登錄銀行網站時瀏覽器可能緩存用戶的賬號及密碼,當用戶登錄其他網站時如果不加以限制,該網站可能拿到用戶的密碼信息並發送到銀行網站進行操作。

但是有時跨域訪問也是需要的,比如有時公司內部有多個不同的子域,比如一個是location.company.com ,而應用是放在app.company.com , 這時想從 app.company.com去訪問 location.company.com 的資源就屬於跨域。

2、跨域的解決方法

2.1、通過JSONP實現跨域

JSONP 是 JSON with padding(填充式 JSON 或參數式 JSON)的簡寫,是應用 JSON 的一種新方法。JSONP 看起來與 JSON 差不多,只不過是被包含在函數調用中的 JSON, 比如:

callback({ "name": "Nicholas" });   //callback:回調函數名  JSONP可以看做就是一段以json為參數的函數調用代碼

JSONP 由兩部分組成:回調函數和數據。回調函數是當響應到來時應該在瀏覽器頁面中調用的函數。

JSONP 是通過<script>標簽來使用的,使用時可以為src 屬性指定一個跨域 URL。這裏的<script>元素與<img>元素類似,都有能力不受限制地從其他域加載資源。因為 JSONP 是有效的 JavaScript 代碼,所以在請求完成後,即在 JSONP 響應加載到頁面中

以後,就會立即執行。

JSONP的原理:通過script標簽引入一個 js 文件,這個 js 文件載入成功後會自動執行在 src 參數中指定的回調函數,並且後端會設計把需要的 json 數據作為參數傳入。所以 jsonp 是需要服務器端進行配合設計的,即後端需獲得前端傳過來的回調函數名,並把需要的json數據作為參數,然後把一段回調函數執行的代碼返回,當前端加載到後端頁面時將受到後端返回的那段代碼,然後自動執行回調函數。

//前端代碼
<script type="text/javascript">
    function dosomething(jsondata){
        console.log(‘數據:‘, jsondata)
    }
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>

//後端代碼
<?php
$callback = $_GET[‘callback‘];//獲取前端傳來的回調函數名
$data = array(‘a‘,‘b‘,‘c‘);//這是要返回的數據
echo $callback.‘(‘.json_encode($data).‘)‘;//輸出 JSONP ,前端拿到這個輸出將會執行這段代碼
?>

可以通過動態創建 script 標簽來實現 JSONP,這樣就不用在 html結構上添加額外的script標簽了

function handleResponse(response){
  console.log(‘數據:‘,response);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild); 


//或者使用jQuery實現
<script type="text/javascript">
    $.getJSON(‘http://example.com/data.php?callback=?,function(jsondata)‘){
        console.log(‘數據:‘,jsondata);
    });
</script>

2.2、CORS實現跨域

CORS跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。

對於前端開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。實現CORS通信的關鍵是服務器端,只要服務器實現了CORS接口,就可以跨源通信。如果服務器端實現了CORS,在進行AJAX請求時,瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求。

CORS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功還是失敗。

服務器端對於CORS的支持,主要就是通過設置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設置,就可以允許Ajax進行跨域的訪問。只需要在後臺中加上響應頭來允許域請求!

//指定允許其他域名訪問
‘Access-Control-Allow-Origin:*‘//或指定域
//響應類型
‘Access-Control-Allow-Methods:GET,POST‘
//響應頭設置
‘Access-Control-Allow-Headers:x-requested-with,content-type‘
//前端代碼,跟一般ajax訪問無區別
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    console.log(xhr.responseText)
  }
}
xhr.open(‘GET‘, ‘http://192.168.2.186:8081/KuayuAjax/server.php‘, true);
xhr.send(null);

//後端代碼
<?php header("Content-Type:text/plain"); header("Access-Control-Allow-Origin:http://localhost:8081");//設置頭部,不設置的話請求會被拒絕 echo ‘{"src":"http://www.pinkbluecp.cn/face_alignment/img/picture.jpg"}‘; ?>

JS中的跨域問題