jQuery – 在 header 修改,解決跨網域 JSON、JSONP 的方法

通常使用 jQuery 要跨網域存取資料,會出現禁止訊息

MLHttpRequest cannot load 連接的伺服器網址. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '你的網址' is therefore not allowed access.

通常我們會改用 JSONP,但是 JSONP 只允許使用 GET 方式處理。可以參考官方建議寫法,我這邊舉例 PHP 與 jQuery

PHP

<?php 

function json($data)
{
    $encode               = json_encode($data);
    $jsonp_callback_key   = 'callback';
    $jsonp_get            = $_GET[$jsonp_callback_key];

    //純json 格式
    if (empty($_GET[$jsonp_callback_key])) 
    {
        return $encode;
    }
    
    //jsonp 方法 
    return "{$jsonp_get}($encode)"; 
}

echo json($_GET);

 

jQuery

$.ajax({
    //伺服器網址
    url: 'http://xxx/server.php',
    // 跨網域使用 jsonp
    dataType: 'jsonp',
    // 可以自訂回傳方法的字串。預設是 callback
    jsonp: 'callback',
    // 規定只能用 GET
    type: "GET",
    // 傳遞的參數
    data: {
        message: 'Hello World'
    },
    // 成功時顯示
    success: function (data){
        console.log(data);
    }
})

上面的 callback() 可以自動處理 json 與 jsonp 的回傳。注意上面這兩個例子的名稱要互相匹配:

  • php 的 $jsonp_callback_key
  • jQuery 的 jsonp

所以實際網址會變成類似這樣

http://xxx/server.php?callback=

 

非 GET 請求怎麼辦?

當 API 設計的要求是 POST、PUT、DELETE …… JSONP 不就沒辦法使用了?後來參考了網友發文發現可以這麼做

PHP

<?php 
// 添加這行,允許跨網域!!
header('Access-Control-Allow-Origin:*');

function json($data)
{
    $encode               = json_encode($data);
    $jsonp_callback_key   = 'callback';
    $jsonp_get            = $_GET[$jsonp_callback_key];

    //純json 格式
    if (empty($_GET[$jsonp_callback_key])) 
    {
        return $encode;
    }
    
    //jsonp 方法 
    return "{$jsonp_get}($encode)"; 
}

echo json($_GET);

設定 header 為 Access-Control-Allow-Origin:* 或 Access-Control-Allow-Origin:允許的網域  就可以使用 JSON 而不使用 JSONP 啦!你也可以改成 header(‘Access-Control-Allow-Origin:http://localhost’); 那就只限制當發生跨網域行為時,只有從本機發出請求才允許。

jQuery

$.ajax({
    url: 'http://xxx/server.php',
    dataType: 'json',
    type: "GET",
    data: {
        message: 'Hello World'
    },
    success: function (data){
        console.log(data);
    }
})

改用 json 以後發現可以成功唷!而且用 POST  一樣沒問題~~

Comments

發表迴響