Laravel 開啓跨域功能

跨域的請求

出於安全性的緣由,瀏覽器會限制 Script 中的跨域請求。因爲 XMLHttpRequest 遵循同源策略,全部使用 XMLHttpRequest 構造 HTTP 請求的應用只能訪問本身的域名,若是須要構造跨域的請求,那麼開發者須要配合瀏覽器作出一些容許跨域的配置。php

W3C 應用工做組推薦了一種跨資源共享的機制,這種機制讓 Web 應用服務器能支持跨站訪問控制,從而使得安全的進行跨站數據傳輸成爲可能,該機制經過幾種方式來對原有模式進行了擴展:跨域

  • 響應的頭部應該追加 Access-Control-Allow-Orign,用來代表哪些請求源被容許訪問資源內容瀏覽器

  • 瀏覽器會對請求源和響應中的值進行匹配驗證緩存

  • 對於跨域的請求,瀏覽器會預發送一個非簡單方式的請求,來判斷給定資源是否準備接受跨域資源訪問安全

  • 服務端應用經過檢查請求頭部的 Orign 來斷定請求是否跨域。服務器

跨源資源共享標準

跨源資源共享標準經過新增一系列 HTTP 頭,讓服務器能聲明哪些來源能夠經過瀏覽器訪問該服務器上的資源。另外,對哪些會對服務器數據形成破壞性響應的 HTTP 請求方法(特別是 GET 之外的 HTTP 方法,或者搭配某些 MIME 類型的 POST 請求),標準強烈要求瀏覽器必須先以 OPTIONS 請求方式發送一個預請求(preflight request),從而獲取知服務器端對跨源請求所支持 HTTP 方法。在確認服務器容許跨源請求的狀況下,以實際的 HTTP 請求方法發送那個真正的請求。服務器端也能夠通知客戶端,是否是須要隨同請求一塊兒發送信用信息(包括 Cookies 和 HTTP 認證相關數據)。cookie

跨源共享標準須要瀏覽器和服務端共同配合才能完成,目前瀏覽器廠商已經能夠將請求部分自動完成,因此跨源資源訪問的重點仍是在於服務器端。session

下面列出一些標準中可用的響應頭和請求頭。app

Response Header

  • Access-Control-Allow-Origin : 指明哪些請求源被容許訪問資源,值能夠爲 "*","null",或者單個源地址。spa

  • Access-Control-Allow-Credentials : 指明當請求中省略 creadentials 標識時響應是否暴露。對於預請求來講,它代表實際的請求中能夠包含用戶憑證。

  • Access-Control-Expose-Headers : 指明哪些頭信息能夠安全的暴露給 CORS API 規範的 API。

  • Access-Control-Max-Age : 指明預請求能夠在預請求緩存中存放多久。

  • Access-Control-Allow-Methods : 對於預請求來講,哪些請求方式能夠用於實際的請求。

  • Access-Control-Allow-Headers : 對於預請求來講,指明瞭哪些頭信息能夠用於實際的請求中。

  • Origin : 指明預請求或者跨域請求的來源。

  • Access-Control-Request-Method : 對於預請求來講,指明哪些預請求中的請求方式能夠被用在實際的請求中。

  • Access-Control-Request-Headers : 指明預請求中的哪些頭信息能夠用於實際的請求中。

Request Header

  • Origin : 代表發送請求或預請求的來源。

  • Access-Control-Request-Method : 在發送預請求時帶該請求頭,代表實際的請求將使用的請求方式。

  • Access-Control-Request-Headers : 在發送預請求時帶有該請求頭,代表實際的請求將攜帶的請求頭。

中間件

在 Laravel 中容許跨域請求,咱們能夠構建一個追加響應的中間件,用來添加專門處理跨域的請求的響應頭:

<?php namespace App\Http\Middleware;

use Closure;
use Response;
class EnableCrossRequestMiddleware {

  /**
   * Handle an incoming request.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @return mixed
   */
  public function handle($request, Closure $next)
  {

    $response = $next($request);
        $response->header('Access-Control-Allow-Origin', config('app.allow'));
        $response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, Accept');
        $response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
        $response->header('Access-Control-Allow-Credentials', 'true');
        return $response;
  }

}

其中有如下須要注意的地方:

  • 對於跨域訪問並須要伴隨認證信息的請求,須要在 XMLHttpRequest 實例中指定 withCredentialstrue

  • 這個中間件你能夠根據本身的需求進行構建,若是須要在請求中伴隨認證信息(包含 cookie,session)那麼你就須要指定 Access-Control-Allow-Credentialstrue, 由於對於預請求來講若是你未指定該響應頭,那麼瀏覽器會直接忽略該響應。

  • 在響應中指定 Access-Control-Allow-Credentialstrue 時,Access-Control-Allow-Origin 不能指定爲 *

  • 後置中間件只有在正常響應時纔會被追加響應頭,而若是出現異常,這時響應是不會通過中間件的。

PS: 歡迎關注簡書 Laravel 專題,也歡迎 Laravel 相關文章的投稿 :),做者知識技能水平有限,若是你有更好的設計方案歡迎討論交流,若是有錯誤的地方也請批評指正,在此表示感謝謝謝 :)

相關文章
相關標籤/搜索