a> jsonp(JSON with Padding):基本原理是動態創建script標籤,遠程調用JSON文件來實現數據傳遞,是一個非官方協議,是一個約定,約定請求的參數中如果包含指定參數(摩默認是callback)這就是一個jsonp請求,伺服器發現是jsonp 請求時候就會把數據由原來的json對象改成js代碼
普通的ajax請求,返回的json對象,而jsonp 請求返回的是js腳本
服務端代碼:
/**
* 跨域測試 服務端介面
* @author zhangyanmin
* @date 2018-04-13
*/
public function crossDomain(){
$data[field1] = a;
$data[field2] = b;
$data[field3] = c;
$data = json_encode($data);
if(isset($_GET[callback])){
echo (.$_GET[callback].(.$data.));
}else{
exit($data);
}
}
客戶端代碼:
$.ajax({
type: "get",
url: "http://test.leku.com:8080/zym/crossDomain",
dataType:jsonp,
data: {callback: jsp_cal},
success: function (res) {
console.log(success);
console.log(res);
},
error: function(){
console.log(error);
}
});
//jsp_cal 為雙方約定的回調函數,默認是 callback
var jsp_cal = function(flag){
console.log(success);
console.log(flag);
}
jsonp 的弊端:
1,需要伺服器端改動代碼支持;
2,只支持get 方法,即使指定post請求也是get方式;
3,發送的不是XHR(新特性支持非同步,各種事件等)請求
3,跨域:
a> 被調用方修改(支持跨域):在響應頭添加指定的欄位,支持跨域請求
1,伺服器端實現
public function addHeader(){
// header(Access-Control-Allow-Origin:*);
// header(Access-Control-Allow-Methods:*);
// 允許 指定域,指定方法跨域請求
header(Access-Control-Allow-Origin:http://test.order.com:8080/);
header(Access-Control-Allow-Methods:GET);
$data[field1] = a;
$data[field2] = b;
$data[field3] = c;
$data = json_encode($data);
exit($data);
}
簡單請求:先執行後判斷,如果發現是跨域請求,會檢測是否允許跨域
非簡單請求:先發送options預檢命令,檢測通過後再發送請求,會請求兩次
發送兩次請求會佔用更多的網路資源,所以就有預檢命令緩存
//將預檢命令緩存一個小時,第一次請求時會發送連個請求,過期之前再請求只發送一次請求
header(Access-Control-Allow-Max-Age:"3600");
帶cookie的跨域請求(發送的是被調用方的cookie)
服務端代碼:
public function getCookie(){
// 帶cookie 時,origin必須完全匹配不能為*
header(Access-Control-Allow-Origin:http://test.order.com:8080);
header(Access-Control-Allow-Methods:*);
// enable cookie
header(Access-Control-Allow-Credentials:true);
}
客戶端代碼:
// 獲取Cookie的請求
$.ajax({
type: "get",
url: "http://test.leku.com:8080/zym/getCookie",
xhrFields:{
withCredentials:true,//發送Ajax時,Request header中便會帶上 Cookie 信息
},
success: function (res) {
console.log(res);
},
error: function(){
console.log(error);
}
});
發送自定義頭的跨域請求
2,修改nginx 配置
var xhr = new XMLHttpRequest();
$.ajax({
type: "get",
url: "http://test.leku.com:8080/zym/getHeader",
headers:{
x-headre1:AAAA,//發送Ajax時,Request header中便會帶上 Cookie 信息
},
beforeSend:function(){
xhr.setRequestHeader(x-headre2,BBBB);
},
success: function (res) {
console.log(res);
},
error: function(){
console.log(error);
}
});
伺服器端代碼
public function getHeader(){
// 帶cookie 時,origin必須完全匹配不能為*
header(Access-Control-Allow-Origin:http://test.order.com:8080);
header(Access-Control-Allow-Methods:*);
//可以在瀏覽器裏複製所有的header信息並返回回去,這樣支持所有的請求頭請求
header(Access-Control-Allow-Headers:Content-Type, x-header1, x-header2);
}
2,修改nginx 配置
server{
………………
location /{
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
if ($request_method = OPTIONS){
return 200;
}
}
}
3,apache 配置
<Directory /www/web/yuming.com/public_html/>
Options FollowSymLinks
AllowOverride All
Require all granted
Header set Access-Control-Allow-Origin *
</Directory>
編輯 httpd.conf
找下面這行,把#去掉,目的是開啟apache頭信息自定義模塊
#LoadModule headers_module modules/mod_headers.so
b> 調用方做修改(隱藏跨域,代理)
調用方通過Http反向代理轉發到被調用方的伺服器
server{
listen 80;
servername a.com;
location /{
proxy_pass http://test.order.com:8080;
}
//代理之後的地址
location /ajaxserver{
proxy_pass http://test.leku.com:8080;
}
}
客戶端代碼
$.ajax({
type: "get",
url: "/ajaxserver",//代理後的地址
success: function (res) {
console.log(res);
},
error: function(){
console.log(error);
}
});
來源:慕課網視頻地址
推薦閱讀: