Laravel 9 - CORS无法工作(XMLHttpRequest的访问已被CORS策略阻止)

11

我正在尝试使用Vuejs构建一个独立的前端Web应用程序,并从我构建的Laravel 9 API获取数据。当我试图从前端访问数据时,浏览器控制台显示以下响应:

XMLHttpRequest在'http://localhost:8000/api'上的访问已被CORS策略阻止:请求的资源上没有'Access-Control-Allow-Origin'标头。

后端代码(Laravel 9)

1- api.php文件

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Models\User;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::get('/', function () {
    $users = User::all();
    return response()->json($users, 200);
});

2- cors.php文件(默认配置)

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => false,

];

前端代码(Vuejs)

import { createApp } from 'vue'

import axios from 'axios'
import VueAxios from 'vue-axios'

import App from './App.vue'

const app = createApp(App)

app.use(VueAxios, axios)
app.mount('#app')

2- Users.vue(获取数据的组件)

<template>
  <div class="users">
    test
    <button @click="getUsers()">Get Users</button>
    {{ users }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: [],
    }
  },
  methods: {
    getUsers() {
      this.axios.get('http://localhost:8000/api').then((response) => {
        // this.users = response;
        // console.log(this.users);
        console.log(response);
      }).catch(err => console.log('error: ' + err));
    }
  }
}

更新:更多说明

我使用了一个Google扩展程序,允许浏览器进行CORS,并且该扩展自动向响应添加以下标头:

a) access-control-allow-methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
b) access-control-allow-methods: *

但我认为不能使用扩展程序作为解决方案,因为我想在生产环境下解决问题,而不仅仅是在调试模式下。

以下是浏览器响应的一些截图。

1- 浏览器中的CORS错误响应

CORS error response in the browser

2- 启用扩展程序之前的响应头数量(仅有9个响应头):

number of the header responses before enabling the extension

3- 启用扩展程序之前的响应头详情(仅有9个响应头):

details of response headers before using the extensions

4- 启用扩展程序之后的响应头数量(有11个响应头):

number of the header responses after enabling the extension ( 11 headers)

5- 启用扩展程序之后的响应头详情(有11个响应头)

enter image description here


2
你有没有在后端遇到问题的机会?当检查请求时,你能否发布一个屏幕截图或网络选项卡中的详细信息? - Potato Science
我对Laravel不是很了解,但可能是cors.php中路径末尾的斜杠引起了问题。您的客户端正在请求http://localhost:8000/api,也许尝试在cors路径中添加'api'。 - Igor Moraru
我已经更新了问题,并提供了更多有关浏览器响应的细节。 - Amr Ragab
1
cors.php一点也没有帮助。 - Amir Khan
5个回答

10

我找到了解决方案,我的问题是尝试从http://localhost:8000/api获取数据时,当我查看cors.php文件时,发现路径键包含2个值,如下所示:
'paths' => ['api/*', 'sanctum/csrf-cookie']
所以就像我说的那样,我正在导航到api路径而不仅仅是api/*,因此数组应该包含“api”值,如下所示:
'paths' => ['api/*', 'sanctum/csrf-cookie', 'api']


当你的Laravel安装不在根目录时,你还需要更改路径。例如:'backend/api/*'。 - RandomUsername
@RandomUsername,“不安装在根目录”是什么意思?这与在软件包和软件包路由中使用有关吗? - DevonDahon
@DevonDahon 我把laravel安装在了web服务器的子文件夹中,而且 CORS 配置对我来说不能只用 'api' 就能工作。我需要在配置中也加入子文件夹才能使其正确工作。 - RandomUsername

6

当我将NuxtJs连接到Laravel API时,也遇到了同样的问题。

在Laravel的cors.php文件中,我所做的就是将'supports_credentials'的值设置为true。默认值为'false'。

希望这能节省您的时间。


1

我已经发现了一个关于CORS问题的独特问题。

在Laravel 9的服务器端上,我没有发现任何CORS问题。

我在客户端上发现了一个问题。

如果您不包含请求头:Accept: application/json,那么您的请求将获得302 Found重定向响应代码,并且这就是您会遇到CORS错误的地方。

希望这能节省您的时间。 :)


0
我在本地主机上遇到了同样的问题,原因是我没有对存储文件夹拥有写入权限。

-2

添加一个新的中间件 app\Http\Middleware\Cors.php

namespace App\Http\Middleware;

use Closure;

class Cors {
    
    public function handle($request, Closure $next) {
        
        $response = $next($request);
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set('Access-Control-Allow-Methods', 'POST, GET');
        $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application', 'ip');
        return $response; 
    }
}

将此行添加到 app\Http\Kernel.php 文件中

protected $middleware = [
         .....,
        \App\Http\Middleware\Cors::class,
    ];

3
不要这样做。Laravel >=8已经默认拥有CORS策略中间件。请查看您的中间件堆栈。它位于Illuminate命名空间下。 - JarsOfJam-Scheduler
1
@JarsOfJam-Scheduler 那么问题的解决方案是什么呢?即使 Laravel 已经有了它,我还是遇到了错误:"已被 CORS 策略阻止:预检请求的响应未能通过访问控制检查:没有 'Access-Control-Allow-Origin'"。 - exSnake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接