没有将 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:publishCorsServiceProvider (如果是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 标头添加到握手的响应中。错误或配置错误?

在 Angular 6 中将 CORS 标头添加到响应中