以前作了一個公司的內部管理系統,如今但願經過在釘釘上開發一個小應用查看相關數據,在此過程當中涉及了HTTP的跨域請求的問題,在瞭解相關信息後,打算基於CORS實現。關於CORS(跨域資源共享),見這篇文章。
CORS中,對於簡單請求,只需在服務器進行相關的字段驗證後進行響應便可,主要是驗證請求的來源及請求的方法等是不是服務器許可的。
而對於複雜請求,則瀏覽器會先發送一個options請求到服務器進行驗證,驗證經過後,再發送用戶的請求。再options請求中,服務器會返回容許的請求源、請求方法及頭部字段等。php
對於CORS在Laravel中的實現須要在項目中加入一箇中間件Cors,html
<?php namespace App\Http\Middleware; use Closure; class Cors { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { header("Access-Control-Allow-Origin: *"); $headers = [ 'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE', 'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin' ]; $response = $next($request); foreach($headers as $key => $value) $response->header($key, $value); return $response; } }
對於簡單請求,好比get請求,在路由中加入該中間件便可。
但對於複雜請求,則處理不了。(根據文檔,POST請求知足某些條件是纔是複雜請求,但不知道爲什麼,我發出的POST請求都是複雜請求,即瀏覽器首先會觸發一次options請求,再提交客戶的實際請求)。
對於只是採起與簡單請求相同的方法,則對於複雜請求沒法正確響應。跨域
如下是GET請求的請求-響應信息:
瀏覽器
如下是POST請求的響應:
服務器
可見POST請求中,瀏覽器先進行了OPTIONS請求,但該請求的響應中,並無GET響應中的cors
Access-Control-Allow-Headers:Content-Type, X-Auth-Token, Origin Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE Access-Control-Allow-Origin:*
等跨域控制字段。學習
經過查詢資料,Laravel對於OPTIONS請求會自動常規響應200。因此缺乏必要的頭部信息。
因此,我經過在路由中專門加入一個處理options的路由spa
Route::options('cors/test',function(){ return response('ok') ->header('Access-Control-Allow-Methods','POST, GET, OPTIONS, PUT, DELETE') ->header('Access-Control-Allow-Headers','Content-Type, X-Auth-Token, Origin'); })->middleware('cors');
即保證了OPTIONS響應了必要的頭部信息。
但該方法須要關閉Laravel中相應路由的CSRF功能,具體在AppHttpMiddlewareVerifyCsrfToken添加code
protected $except = [ 'cors/*' ];
雖然解決了問題,但對於其中的不少細節仍是不瞭解,須要進一步學習。htm