項目中用到了接口,外部調用的時候老是請求不到,本地請求卻沒問題,查了下說是因為跨域的問題。
根據網上所說解決方法如下:
1、
建立中間件Cors.php
指令:
php artisan make:middleware Cors
在
/app/Http/Middleware/
目錄下會出現一個
Cors.php
檔案。
2、
在
handle
方法中加入如下内容:
$response = $next($request);
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, Accept, multipart/form-data, application/json');
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
$response->header('Access-Control-Allow-Credentials', 'false');
return $response;
其中有以下需要注意的地方:
- 對于跨域通路并需要伴随認證資訊的請求,需要在 XMLHttpRequest 執行個體中指定 withCredentials 為 true。
- 這個中間件你可以根據自己的需求進行建構,如果需要在請求中伴随認證資訊(包含 cookie,session)那麼你就需要指定 Access-Control-Allow-Credentials 為 true, 因為對于預請求來說如果你未指定該響應頭,那麼浏覽器會直接忽略該響應。
- 在響應中指定 Access-Control-Allow-Credentials 為 true 時,Access-Control-Allow-Origin 不能指定為 *(這個一定要注意,我就是在這個地方調了好久)
- 後置中間件隻有在正常響應時才會被追加響應頭,而如果出現異常,這時響應是不會經過中間件的。
Cors.php檔案内容如下:
<?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)
{
$response = $next($request);
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, Accept, multipart/form-data, application/json');
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
$response->header('Access-Control-Allow-Credentials', 'false');
return $response;
}
}
3、在 Kernel.php檔案中的$middleware中加入剛剛添加的中間件:
\App\Http\Middleware\Cors::class,
如:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Cors::class,
];
以下内容為網絡摘抄:
跨源資源共享标準
跨源資源共享标準通過新增一系列 HTTP 頭,讓伺服器能聲明哪些來源可以通過浏覽器通路該伺服器上的資源。另外,對哪些會對伺服器資料造成破壞性響應的 HTTP 請求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些 MIME 類型的 POST 請求),标準強烈要求浏覽器必須先以 OPTIONS 請求方式發送一個預請求(preflight request),進而擷取知伺服器端對跨源請求所支援 HTTP 方法。在确認伺服器允許跨源請求的情況下,以實際的 HTTP 請求方法發送那個真正的請求。伺服器端也可以通知用戶端,是不是需要随同請求一起發送信用資訊(包括 Cookies 和 HTTP 認證相關資料)。
跨源共享标準需要浏覽器和服務端共同配合才能完成,目前浏覽器廠商已經可以将請求部分自動完成,是以跨源資源通路的重點還是在于伺服器端。
下面列出一些标準中可用的響應頭和請求頭。
Response Header
Access-Control-Allow-Origin : 指明哪些請求源被允許通路資源,值可以為 “*”,”null”,或者單個源位址。
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 : 在發送預請求時帶有該請求頭,表明實際的請求将攜帶的請求頭。
本文位址:http://blog.csdn.net/leedaning/article/details/53787008
允許多域名跨域
$response = $next($request);
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
$allow_origin = array(
'http://127.0.0.1:8080',
'htp://www.game.com',
'http://www.gameadmin.com'
);
if (in_array($origin, $allow_origin)) {
$response->header('Access-Control-Allow-Origin', $origin);
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, Accept, multipart/form-data, application/json');
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
$response->header('Access-Control-Allow-Credentials', 'true');
}
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');
這是因為delete或者PUT請求會失敗。
這個時候隻能比對一個位址,對我們來說完全不夠呀。
隻能通配符适配才行。然後有了下面一段代碼。在上面的代碼上再跟進一步
Route::options('/{all}',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')->where(['all' => '([a-zA-Z0-9-]|/)+']);