没有将 Cors 标头添加到响应中
Posted
技术标签:
【中文标题】没有将 Cors 标头添加到响应中【英文标题】:No Cors headers added to response 【发布时间】:2019-09-05 21:15:08 【问题描述】:当尝试从 React 应用程序使用 API(本地托管)登录时,我每次都会收到此错误:
我知道有很多关于这个主题的主题,但没有一个对我有帮助。也许是因为我错过了一些东西,或者不明白这个概念。
我不知道如何解决这个问题。
我已经尝试过的事情:
- 添加了一个 HTTP 中间件(代码如下):没用。
- 尝试使用 spatie/laravel-cors
包修复它:没用。
- 尝试使用barryvdh/laravel-cors
修复它:也没有用。
我没有想法。有人知道我做错了什么吗?
我的代码
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\Spatie\Cors\Cors::class, // <-- this line would be pointed to my own middleware when that would be in use
];
如果我在哪里使用自己的中间件,则指向以下代码而不是 \Spatie\Cors\Cors::class
class ApiCors
/**
* 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, PUT, DELETE, OPTIONS, PATCH')
->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
【问题讨论】:
你是在 api 服务器上做的,对吧? 是的,我是@Styx 你没有忘记vendor:publish
CorsServiceProvider
(如果是spatie/laravel-cors
),对吧?
@Styx 确实有效。谢谢!但是你知道为什么它现在可以工作,而不是我尝试应用的中间件吗?我不想依赖外部依赖。
老实说,不知道。我只是尝试在新制作的项目中使用您的代码使用ApiCors
中间件,它按预期工作。也许您忘记注释掉VerifyCsrfToken
中间件或添加\App\Http\Middleware\ApiCors::class
?
【参考方案1】:
实现 CORS 支持有一些棘手的问题:
您的 CORS 中间件应该添加到 global 中间件堆栈中,因为浏览器可以发送 Preflight 请求,并且您不希望每个 API 路由都有特定的 OPTIONS
路由。
中间件不需要将预检请求更深入地传递给应用程序。
CORS 标头应同时添加到 Preflight 请求和 API 请求中。
所以,应该是这样的:
创建中间件:
php artisan make:middleware ApiCors
放代码:
<?php
namespace App\Http\Middleware;
use Closure;
class ApiCors
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
$isPreflight = $request->isMethod('options') && $request->hasHeader('origin');
// we don't need to process Preflight request further
$response = $isPreflight ? response()->make() : $next($request);
if($isPreflight)
$response
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH')
->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization')
->header('Access-Control-Max-Age', 86400);
$response->header('Access-Control-Allow-Origin', $isPreflight ? '*' : ($request->header('origin') ?? '*'));
return $response;
注册中间件:
app/Http/Kernel.php
:
<?php
// ...
use App\Http\Middleware\ApiCors;
class Kernel extends HttpKernel
// ...
protected $middleware = [
// ...
ApiCors::class,
];
// ...
protected $middlewarePriority = [
ApiCors::class, // move to the top of the chain
// ...
];
测试中间件:
让我们添加简单的 API 路由。
routes/api.php
:
Route::put('/v1/test', function ()
return response()->json(['answer' => 42]);
);
让我们启动简单的服务器(在 Laravel 项目根文件夹中运行):
php -S localhost:8088 -t public
接下来,打开任意网页(或使用当前网页)并在开发者控制台中运行:
fetch('http://localhost:8088/api/v1/test',
method: 'PUT', headers: 'accept': 'application/json'
).then(r => r.json()).then(console.log.bind(console))
你应该得到回应:
answer: 42
不要忘记您应该将 [external] API 路由添加到 routes/api.php
,不要 添加到 routes/web.php
,因为 Web 路由器组有许多中间件,它们可能会干扰您的 api 的,比如VerifyCsrfToken
。
MDN: Cross-Origin Resource Sharing (CORS)
【讨论】:
以上是关于没有将 Cors 标头添加到响应中的主要内容,如果未能解决你的问题,请参考以下文章
是否可以将 CORS 标头添加到来自 Tomcat 容器中 j_security_check 的响应
如何将 CORS 标头添加到 Jersey 2 中灰熊服务器的 StaticHttpHandler 提供的响应?
尽管端点在 apicontroller 内部的行为中使用了 cors 类,但 CORS 标头未添加到响应中
将标头添加到 oauth/token 响应(spring-security)
NestJs Socket io 适配器:如果使用 false 调用 allowFunction,服务器不会将 CORS 标头添加到握手的响应中。错误或配置错误?