可怕的CORS错误:
阻止跨源请求:同源策略禁止读取 http://localhost/mysite/api/test处的远程资源。 (原因:CORS 标题' Access-Control-Allow-Origin'丢失)。
Laravel路线:
$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router) {
$router->get('/test', 'MyController@myMethod');
});
Laravel Cors Middlware:
public function handle($request, Closure $next)
{
header('Access-Control-Allow-Origin: *');
// ALLOW OPTIONS METHOD
$headers = [
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers' => 'Content-Type, X-Auth-Token, Origin, Authorization'
];
if ($request->getMethod() == "OPTIONS") {
// The client-side application can set only headers allowed in Access-Control-Allow-Headers
return Response::make('OK', 200, $headers);
}
$response = $next($request);
foreach ($headers as $key => $value)
$response->header($key, $value);
return $response;
}
Laravel Kernel:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'cors' => \App\Http\Middleware\CORS::class
];
相关.htaccess:
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
相关的Vue.js:
new Vue({
el: '#app',
data: {
//data here
},
http: {
headers: {
"Authorization": "Basic " + "apiKeyHere"
}
},
methods: {
mymethod: function (e)
{
e.preventDefault();
this.$http.get('http://localhost/mysite/api/test').then(
function (response)
{
//do something
}
)
}
}
});
如果我取出Authorization标头选项,则请求有效。
我也试过https://github.com/barryvdh/laravel-cors但仍然没有快乐。 任何帮助表示赞赏!
答案 0 :(得分:22)
显然不是理想的解决方案,但它起作用。我已经将它添加到我的routes.php文件的顶部:
header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
在没有黑客的情况下让它工作真是太好了......唉。
更新:原来是IIS相关。我最终在web.config文件中设置了标题,现在CORS可以在不破坏routes.php文件的情况下工作。
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Headers" value="Origin, Authorization, X-Requested-With, Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
</customHeaders>
</httpProtocol>
如果要限制访问权限,可以添加出站规则:
<outboundRules>
<clear />
<rule name="AddCrossDomainHeader">
<match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?somesite\.com|(.+\.)?anothersite\.org))" />
</conditions>
<action type="Rewrite" value="{C:0}" />
</rule>
</outboundRules>
答案 1 :(得分:14)
我解决了我的问题,只需在我的routes.php Laravel 5.2上添加这些行 对于大于5.2的routes / web.php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin, Authorization');
在全局HTTP中间件堆栈中注册Cors中间件
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\CorsMiddleware::class
];
答案 2 :(得分:6)
您的中间件还可以,但您需要在全球HTTP中间件堆栈中注册Cors中间件。
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\CorsMiddleware::class
];
答案 3 :(得分:3)
这个问题确实来自于预检请求,但是当我们谈论Laravel时,处理方式需要一些额外的解释 - 主要是OPTIONS
请求被路由(其他答案反而是PHP)方式,而不是Laravel方式),所以,你必须将它添加到你的路线才能成功:
Route::options('/{any}', function(){ return ''; })->where('any', '.*');
现在,让我们迎合所有其他方法 - 创建CORS中间件:
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', 'GET, POST, PATCH, PUT, DELETE');
}
}
最后,对于给定的路由,请使用该中间件:
Route::put('/test', function(){ echo('test'); })->with('cors');
答案 4 :(得分:2)
你可以绕过这个没有像Barryvdh \ Cors for Laravel这样与JWT AUTH无法正常工作的中间件,我已经在内核实例化之前在Laravel的index.php中添加了以下语句
header('Access-Control-Allow-Origin: http://localhost:8001');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token,Authorization');
header('Access-Control-Allow-Credentials: true');
在
之前加上这个$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
这也适用于JWT AUTH。 请注意,在Access-Control-Allow-Headers中,您应该包含授权,否则授权标头将不允许您的accesstoken,因此JWT AUTH将失败。 快乐编码。
答案 5 :(得分:0)
我的解决方案:
$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router){
$router->options('{param1?}/{param2?}/{param3?}', function () {});
});
答案 6 :(得分:0)
即使将中间件直接放入$middleware
而不是$routeMiddleware
或只是在app.php中全局定义标头,这都是一个可怕的决定,因为它将暴露所有端点使用新的CORS政策,以防万一您只想将API的一部分公开给第三方解决方案。
更好的解决方案是仅允许OPTIONS调用在所有端点上通过,并且仍然通过$routeMiddleware
重定向其他HTTP方法,以便仅在一部分端点上限制CORS策略。
因此,构建两个中间件:
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', '*');
}
}
OptionsCors.php
<?php
namespace App\Http\Middleware;
use Closure;
class OptionsCors
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if($request->isMethod('OPTIONS')) {
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', '*')
->header('Access-Control-Allow-Headers', '*');
}
return $next($request);
}
}
app / Http / Kernel.php
<?php
namespace App\Http
{
class Kernel extends \Illuminate\Foundation\Http\Kernel
{
protected $middleware = [
// ...
'App\Http\Middleware\OptionsCors',
];
protected $middlewareGroups = [
'web' => [
// ...
],
'api' => [
'App\Http\Middleware\UseApiGuard',
'throttle:60,1',
'bindings'
]
];
protected $routeMiddleware = [
// ...
'cors' => 'App\Http\Middleware\Cors',
];
}
}
现在,在您的路由中,您将完全控制收紧的CORS政策将暴露哪些端点:
Route::namespace('Api')->middleware(['cors'])->group(function () {
Route::get('api/im_open', 'TestController@ping');
});
Route::namespace('Api')->group(function () {
Route::get('api/im_closed', 'TestController@ping');
});
答案 7 :(得分:0)
我通过在 bootstrap/app.php 中添加标题轻松解决了我的问题
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
答案 8 :(得分:-1)
此答案基于此article。 barryvdh/laravel-cors中间件库,可用于解决问题(跨源资源共享)。
第1步安装它:
composer require barryvdh/laravel-cors
第2步:发布图书馆的供应商文件:
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
第3步在第2步中运行的命令会将cors.php文件复制到config目录,如下所示:
return [
/*
|--------------------------------------------------------------------------
| Laravel CORS
|--------------------------------------------------------------------------
|
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
| to accept any value.
|
*/
'supportsCredentials' => false,
'allowedOrigins' => ['*'],// ex: ['abc.com', 'api.abc.com']
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'],// ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
];
对于allowedOrigins
,值可以是['*']
,表示请求的来源可以来自任何域,也可以是特定域的数组,这些域可以是我们允许发送请求的来源到我们的api
,就像['first.com', 'second.com', 'register.third.com']
以及allowedMethods
可以是['*']
,也可以是允许的HTTP verbs
列表,例如['POST', 'GET']
第4步注册cors中间件。打开app/Http/kernel.php
并将HandleCors
课程添加到$routeMiddleware
,如下所示:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'cors' => \Barryvdh\Cors\HandleCors::class, // add this line to enable cors to your routes
];
第5步现在,您可以将laravel-cors
中间件添加到您想要的任何路由中。例如,在Routes/api.php
我会这样做:
Route::apiResource('category', 'CategoryController')->middleware('cors');
Route::apiResource('product', 'ProductController')->middleware('cors');