Laravel 开发 Api 时 access-control-allow-origin 重复定义错误

534 阅读1分钟

基础环境

Laravel:9.5.1

php:8.1

前端项目访问地址:http://127.0.0.1

后端项目访问地址:http://127.0.0.1:8090

问题描述

在用 Laravel 开发 api 接口的时候,在 nginx 配置了允许跨域 add_header Access-Control-Allow-Origin *;

但是在前端使用 VUE 跨域调用我的 api 的时候,提示跨域配置重复定义的错误,如下:

Access to XMLHttpRequest at 'http://127.0.0.1:8090/api/disk/search?word=java&page=1&timestamp=1649492320000' from origin 'http://127.0.0.1' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

通过对访问标头的查看,可以发现有两个跨域的配置:

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *

解决方案

分析原因

通过查询,实际上是由于 fruitcake/laravel-cors 包导致的错误。在 Laravel 中如果 prefix 为 api 则自动添加跨域的 header 头。

vendor\Fruitcake\Cors\CorsService 中,有这样一段代码,可以看到对 header 的操作。

private function configureAllowedOrigin(Response $response, Request $request): void
{
  if ($this->allowAllOrigins === true && !$this->supportsCredentials) {
    // Safe+cacheable, allow everything
    $response->headers->set('Access-Control-Allow-Origin', '*');
  } elseif ($this->isSingleOriginAllowed()) {
    // Single origins can be safely set
    $response->headers->set('Access-Control-Allow-Origin', array_values($this->allowedOrigins)[0]);
  } else {
    // For dynamic headers, set the requested Origin header when set and allowed
    if ($this->isCorsRequest($request) && $this->isOriginAllowed($request)) {
      $response->headers->set('Access-Control-Allow-Origin', (string) $request->headers->get('Origin'));
    }
​
    $this->varyHeader($response, 'Origin');
  }
}

解决过程

App\Http\Kernel 中,只需要注释掉 HandleCors::class 就可以解决问题。

protected $middleware = [
    // ... 此处略去 ...
    // \Illuminate\Http\Middleware\HandleCors::class,
    // ... 此处略去 ...
];

然后再次请求,就OK了。