跨域資源共享 CORS (Cross-origin resource sharing) 是一個 W3C 標準
這裡主要針對 php (Laravel) 以及 nginx 如何設置 CORS 進行說明
以及 Laravel 5.5 之後的版本自定義 cros Middleware 踩過的坑進行紀錄
首先,先看一般原生PHP設定 cors 的方式
PHP 設置 cors header
這裡是常見的設定方式:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: *");
header("Access-Control-Allow-Headers: Origin, Methods, Content-Type");
Access-Control-Allow-Origin : 允許的域名,*代表全部 Access-Control-Allow-Methods : 允許跨域請求的方法 (GET, POST, PUT, DELETE..),*代表全部 Access-Control-Allow-Headers : 允許Header夾帶的訊息參數 Access-Control-Allow-Credentials : 允許發送 cookie (布林值)
JWT 跨域 CORS 請求問題
在使用 JWT Header夾帶 token 跨域請求時,遇到了下列問題
Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS policy: Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
檢查原始的 cors 設定如下:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: *");
header("Access-Control-Allow-Headers: Origin, Methods, Content-Type");
發現,原來是 JWT api 請求在 Header 夾帶的 Authorization 尚未設定在允許清單
在後端程式碼加上去,前端就能正常與API溝通
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: *");
header("Access-Control-Allow-Headers: Origin, Methods, Content-Type, Authorization");
Laravel 自建 Cors Middleware 設置跨域請求
在 Laravel 5.4以前的版本
可以直接建立一個 Cors Middleware,例如:
app/Http/Middleware/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)
{
return $next($request)->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', '*')
->header('Access-Control-Allow-Headers', 'Origin, Methods, Content-Type, Authorization')
->header('Access-Control-Allow-Credentials', true);
}
}
在 app/Http/Kernel.php 裡面的 $routeMiddleware 新增引用
'cors' => \App\Http\Middleware\Cors::class,
就能直接在 route 裡使用,例如:
Route::group(['prefix' => $site, 'middleware' => ['cors']], function () {
但是,在 Laravel 5.5 之後的版本若按照這樣的設置流程,仍會出現問題:
Access to XMLHttpRequest at 'http://xxxx' from origin 'http://xxxxx' has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
[ 解決方式 ]
在 app/Http/Kernel.php 裡面的 $middleware 新增引用 Cors MiddleWare 即可:
\App\Http\Middleware\Cors::class
使用 Laravel Cors 拓展
除了上面的方式,也可以使用 laravel-cors
可直接參考官方教學流程 https://github.com/barryvdh/laravel-cors
直接在 Web Server 設置跨域允許設定
在 Nginx 的 default.conf 直接設定,例如:
location ~ \.php$ {
set $cors "true";
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' '*';
add_header 'Access-Control-Allow-Headers' 'Origin, Method, Content-type, Authorization';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Allow' 'POST, GET, OPTIONS, PUT, DELETE';
try_files $uri /index.php =404;
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fixes timeouts
fastcgi_read_timeout 600;
include fastcgi_params;
}
設置完成之後,再重啟 nginx server 即可
最後提醒,如果再 Nginx 設定,就必須移除 PHP 中的 CORS
避免重複定義 HEADER 規則導致錯誤