问题:
利用了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了)