問題:
利用了laravel開的接口,然後活動部分是用H5做的,方便更新,沒有使用客戶端原生,但是用H5請求接口是報了跨域問題。
jquery.min.js:4 Access to XMLHttpRequest at 'http://**.**.**.**:8085/index.php/and/v2.0.0/partner/answer' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
send @ jquery.min.js:4
ajax @ jquery.min.js:4
(anonymous) @ index.html:205
dispatch @ jquery.min.js:3
r.handle @ jquery.min.js:3
jquery.min.js:4 POST http://**.**.**.**:8085/index.php/and/v2.0.0/partner/answer net::ERR_FAILED
解決方案
-
前端採用JsonP請求,或者利用框架請求
-
PHP接口的方法裏添加
header
header('Access-Control-Allow-Origin:*'); // 響應類型 header('Access-Control-Allow-Methods:*'); //請求頭 header('Access-Control-Allow-Headers:*'); // 響應頭設置 header('Access-Control-Allow-Credentials:false');//cookie 置爲true
-
NGINX代理設置
server { listen 8084; server_name localhost; location /index.php/ { proxy_pass http://localhost:8085; # 指定允許跨域的方法,*代表所有 add_header Access-Control-Allow-Methods *; # 預檢命令的緩存,如果不緩存每次會發送兩次請求 add_header Access-Control-Max-Age 3600; # 帶cookie請求需要加上這個字段,並設置爲true add_header Access-Control-Allow-Credentials true; # 表示允許這個域跨域調用(客戶端發送請求的域名和端口) # $http_origin動態獲取請求客戶端請求的域 不用*的原因是帶cookie的請求不支持*號 add_header Access-Control-Allow-Origin $http_origin; # 表示請求頭的字段 動態獲取 add_header Access-Control-Allow-Headers $http_access_control_request_headers; # OPTIONS預檢命令,預檢命令通過時才發送請求 # 檢查請求的類型是不是預檢命令 if ($request_method = OPTIONS){ return 200; } } }
-
利用laravel第三方包
composer require barryvdh/laravel-cors
位於:config/app.php,添加下面代碼 Barryvdh\Cors\ServiceProvider::class, 全局使用: 如果作爲全局使用的中間件,則直接加入到 middleware 中即可: 修改 app/Http/kernel.php 文件: protected $middleware = [ // ... \Barryvdh\Cors\HandleCors::class, ]; 中間件組使用 如果只是在中間件組中使用,則加入相應的中間件組就OK protected $middlewareGroups = [ 'web' => [ // ... ], 'api' => [ // ... \Barryvdh\Cors\HandleCors::class, ], ]; 配置選項 導出配置: php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider" 配置的基本內容: return [ /* |-------------------------------------------------------------------------- | Laravel CORS |-------------------------------------------------------------------------- | | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*') | to accept any value. | */ 'supportsCredentials' => false, 'allowedOrigins' => ['*'], 'allowedHeaders' => ['Content-Type', 'X-Requested-With'], 'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE'] 'exposedHeaders' => [], 'maxAge' => 0, ]
-
自己準備中間件
創建中間件:
<?php /** * Created by PhpStorm. * User: machi * Date: 2018/5/24 * Time: 下午2:39 */ namespace App\Http\Middleware; use Illuminate\Http\Request; use Closure; class Cors { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { if(!empty($_SERVER["HTTP_ORIGIN"])){ $allow_origin=$_SERVER["HTTP_ORIGIN"]; }else{ $allow_origin='http://test.senpuyun.com'; } if(strtoupper($_SERVER['REQUEST_METHOD'])== 'OPTIONS'){ return response('ok',200) ->header('Access-Control-Allow-Origin', $allow_origin) ->header('Access-Control-Allow-Credentials','true') ->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') ->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS, DELETE,HEAD'); }else{ $response = $next($request); $response->header('Access-Control-Allow-Origin', $allow_origin); $response->header('Access-Control-Allow-Credentials','true'); $response->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); $response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS, DELETE,HEAD'); return $response; } } }
註冊:
bootstrap/app.php$app->routeMiddleware([ 'auth' => App\Http\Middleware\Authenticate::class, 'jwtauth' => App\Http\Middleware\JwtAuthenticate::class, 'jwtrefresh' => App\Http\Middleware\JwtRefreshToken::class, 'partner' => App\Http\Middleware\Partner::class, 'cors' =>\App\Http\Middleware\Cors::class, //'jwt.auth' => Tymon\JWTAuth\Middleware\GetUserFromToken::class, //'jwt.refresh' => Tymon\JWTAuth\Middleware\RefreshToken::class, ]);
路徑配置:
$app->group(['prefix' => 'and/{version}'], function () use($app){ $app->group(['middleware' => 'cors'], function($api) { $api->group(['middleware' => 'partner'], function($api1) { $api1->post('partner/answer', ['as' => 'partner.answer', 'uses' => 'PartnerController@answer']); }); }); )};
本人用的最後一種方法。然後大家需要注意避免重複設置。重複設置可能會出現錯誤
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed
, contains multiple values “*” 意思就是設置了2次跨域,但是隻有一個是允許的,移除其中的任意一個就好了。如果服務器設置了允許跨域,使用Nginx代理裏面就不需要了(或者就不用使用Nginx了)