1. 程式人生 > 其它 >ajax跨域介面

ajax跨域介面

什麼是跨域訪問?

跨域,指的是從一個域名去請求另外一個域名的資源。即跨域名請求!跨域時,瀏覽器不能執行其他域名網站的指令碼,是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。

不同的協議,域名,埠 都是跨域訪問

什麼是同源策略

同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協議+域名+埠"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。

同源策略限制內容有:

  • Cookie、LocalStorage、IndexedDB 等儲存性內容
  • DOM 節點
  • AJAX 請求傳送後,結果被瀏覽器攔截了

但是有三個標籤是允許跨域載入資源:

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

常見跨域場景有哪些?

當協議、子域名、主域名、埠號中任意一個不相同時,都算作不同域。不同域之間相互請求資源,就算作“跨域”。

常見跨域場景如下圖所示:

特別說明兩點:

第一:如果是協議和埠造成的跨域問題,那麼“前臺”是無能為力的。

第二:在跨域問題上,僅僅是通過“URL的首部”來識別,而不會根據域名對應的IP地址是否相同來判斷。“URL的首部”可以理解為“協議, 域名和埠必須匹配”。

這裡你或許有個疑問:請求跨域了,那麼請求到底發出去沒有?

跨域並不是請求發不出去,請求能發出去,服務端能收到請求並正常返回結果,只是結果被瀏覽器攔截了。

你可能會疑問明明通過表單的方式可以發起跨域請求,為什麼 Ajax 就不會?因為歸根結底,跨域是為了阻止使用者讀取到另一個域名下的內容,Ajax 可以獲取響應,瀏覽器認為這不安全,所以攔截了響應。

但是表單並不會獲取新的內容,所以可以發起跨域請求。同時也說明了跨域並不能完全阻止 CSRF,因為請求畢竟是發出去了。


PHP解決跨域問題的方法

跨域的嚴格一點來說就是隻要協議,域名,埠有任何一個的不同,就被當作是跨域。

比如,在實際專案中由於前後端分離當前端需要通過介面向後臺發起請求,此時就會出現跨域問題,那麼,這類問題需要如何解決呢?

其實php解決跨域問題很簡單,只需加上下面的程式碼就可以了:

header("Access-Control-Allow-Origin:*");

加上這行程式碼表示允許所有的域名訪問,不過為了安全起見,在實際專案中往往會限定只允許固定的幾個域名和方法發起的請求。

1、允許單個域名訪問

header('Access-Control-Allow-Origin:http://www.startphp.cn');
header('Access-Control-Allow-Methods:POST');    //表示只允許POST請求
header('Access-Control-Allow-Headers:x-requested-with, content-type'); //請求頭的限制

2、不限制域名

header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST');//表示只允許POST請求
header('Access-Control-Allow-Headers:x-requested-with, content-type');

3、允許多個域名訪問

在實際專案中最好指定能跨域訪問的域名,增加安全性。可以寫在一個公共類裡面,封裝一個方法呼叫。

// 設定能訪問的域名
static public $originarr = [
   'https://test1.com',
   'https://test2.com',
];

/**
 *  公共方法呼叫
 */
static public function setheader()
{
   // 獲取當前跨域域名
   $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
   if (in_array($origin, self::$originarr)) {
      // 允許 $originarr 陣列內的 域名跨域訪問
      header('Access-Control-Allow-Origin:' . $origin);
      // 響應型別
      header('Access-Control-Allow-Methods:POST,GET');
      // 帶 cookie 的跨域訪問
      header('Access-Control-Allow-Credentials: true');
      // 響應頭設定
      header('Access-Control-Allow-Headers:x-requested-with,Content-Type,X-CSRF-Token');
   }
}