在Laravel 5.3 Passport中添加Access-Control-Allow-Origin响应头

92

我是 Laravel 的新手,正在使用 OAuth2.0 密码授权来完成一些 Laravel 5.3 Passport 项目。当我使用参数访问 API 时,它会响应标记。但是,在浏览器中,由于我的请求来自本地主机,而 API 位于我的虚拟机中,所以终端点需要添加额外的安全性。这里是错误信息:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 400.

我知道问题出在哪里,但我不知道该把那个头文件放到哪里,因为这是一个第三方应用程序。

提前感谢专家们。请帮忙。


1
这个回答解决了你的问题吗?Laravel 5.2 CORS,GET与预检OPTIONS不起作用 - Martin Braun
18个回答

214

简单的答案是将 Access-Control-Allow-Origin 头设置为 localhost*。以下是我通常的做法:

创建一个名为 Cors 的简单中间件:

php artisan make:middleware Cors

将以下代码添加到app/Http/Middleware/Cors.php中:

```php
class Cors { public function handle($request, Closure $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); } } ```
public function handle($request, Closure $next)
{
    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}

您可以将*替换为localhost,或者保留其原样。

下一步是加载中间件。请将以下行添加到app/Http/Kernel.php文件中的$routeMiddleware数组中。

'cors' => \App\Http\Middleware\Cors::class, 

最后一步是在要设置访问来源头的路由上使用中间件。假设您正在谈论laravel 5.3中的新api路由,则应该在 app/Providers/RouteServiceProvider.php 文件中的 mapApiRoutes() 函数内执行(您可以删除或注释该函数的以前代码):

    Route::group([
        'middleware' => ['api', 'cors'],
        'namespace' => $this->namespace,
        'prefix' => 'api',
    ], function ($router) {
         //Add you routes here, for example:
         Route::apiResource('/posts','PostController');
    });

9
我也在尝试让它工作(请参见此处),但由于某种原因,只有 GET 请求有效。你知道为什么我的设置不能与 POST 一起工作吗?另外,中间件的顺序似乎很重要。 - Stefan Falk
我正在进行ajax调用,但这个解决方案对我不起作用,有什么建议吗? - Rajesh Vishnani
4
非常清晰,适用于我的Laravel 5.6和Angular 5应用程序。谢谢! - Andrew Koper
2
不要在最后一步添加,只需将以下内容添加到路由的末尾:Route::get('/url','controller@function') -> middleware('cors'); - davefrassoni
Laravel 8已经包含了CORS中间件。但对我而言仍然无法工作(不需要身份验证,因为没有用户存储在数据库中)。 - trainoasis
我正在尝试在我的Laravel 9.x中实现这个功能,目标是从前端发出API请求,但仍然存在CORS问题!有什么建议吗? - Harry

75
简单的答案是将Access-Control-Allow-Origin标头设置为localhost或*。这是我通常的做法:将以下代码添加到bootstrap/app.php中:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');

警告:只在您的开发环境中执行此操作。


2
我认为应该是这样的:header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With,Authorization, Content-Type, Accept'); - diogopalhais
4
如果您允许任何人发布到整个应用程序,这会使您的应用程序容易受到攻击吗? - Brad Ahrens
2
仅供开发使用,可以正常工作。谢谢。 - Jamaluddin Rumi
1
终于有适用于 Laravel 8 的东西了。 - Gass
1
在我的L8上没有起作用。 - Hashim Aziz
显示剩余2条评论

25

你还可以使用由barryvdh创建的出色的laravel-cors包

安装了该软件包后,为了让所有路由都获得CORS支持,最简单的方法是在 Http/Kernel.php 中添加如下中间件:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Barryvdh\Cors\HandleCors::class,
];
如果您不希望在所有路由上都启用CORS支持,您应该为/oauth/token创建一个新的OPTIONS路由,并仅将cors中间件添加到该路由上。 Laravel 8编辑 Laravel 8已经内置了CORS支持-默认情况下,HandleCors中间件在全局中间件栈中定义,并且可以在应用程序的config/cors.php配置文件中进行配置。 如果您更新了Laravel应用程序,请确保使用提供的中间件更改barryvdh的软件包:\Fruitcake\Cors\HandleCors::class

现在应该使用\Fruitcake\Cors\HandleCors::class,而不是\Barryvdh\Cors\HandleCors::class文档 - ibnɘꟻ
config/cors.php 中,Access-Control-Allow-Origin: * 的配置应该是什么? 没有人告诉我。 - undefined

10

对于那些没有解决在App\Http\Kernel中设置路由中间件的问题的人,请尝试设置全局中间件。在App\Http\Middleware\Cors中:

public function handle($request, Closure $next)
{
    return $next($request)->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods','GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS')
        ->header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}

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

这个可行!!!之前将Cors中间件作为路由中间件,无法解决OPTIONS方法请求(Preflight)。 将Cors设置为全局中间件可以处理所有传入的请求,包括Preflight请求。 此外,如果allow-credentials为true,则将allow-origin设置为*将不起作用。在Allow-Credentials为true的情况下,原点必须是特定的。 可以从请求头中获取原点,然后将其添加到响应头中。 - 1nfern0
这个方法对我有效。如果不起作用,你可以尝试在隐身页面。 - Jeyhun Rashidov

7
在App/Http/Middleware中创建一个Cors.php文件,并将以下内容粘贴到其中。
<?php
    
namespace App\Http\Middleware;
    
use Closure;
    
    
class Cors 
{   
    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()->json('OK',200,$headers);
            }
            $response = $next($request);
            foreach ($headers as $key => $value) {
                $response->header($key, $value);
            }
            return $response;
        }
}

在您的Kernel.php文件中,在“Trust Proxies :: Class”行后添加此行。

\App\Http\Middleware\Cors::class,

完成了,你已经允许了所有的CORS头部。


4

https://github.com/fruitcake/laravel-cors 之后,我必须按照以下方式更改cors.php文件

/*
 * Sets the Access-Control-Allow-Credentials header.
 */
'supports_credentials' => true,

在laravel的config/cors.php文件中设置以上键值'supports_credentials' => true后,清除您的配置缓存(php artisan config:clear)、路由缓存(php artisan route:clear)和普通缓存(php artisan cache:clear)。它将为cors.php文件中定义的路径正常工作。 - ANIL PATEL

4

只需将此添加到您的代码控制器

return response()->json(compact('token'))->header("Access-Control-Allow-Origin",  "*");

请始终将您的答案放在内容中,而不是简单地粘贴代码,谢谢! - gehbiszumeis
你能解释一下为什么吗? - jhon

3
请注意,您不能修改预检请求。此外,浏览器(至少是Chrome)会删除“授权”标头...这可能会导致一些问题,根据路由设计可能会出现问题。例如,预检请求将永远不会进入护照路线表,因为它没有带有令牌的标头。
如果您正在设计一个具有选项方法实现的文件,则必须在路由文件web.php中定义一个(或多个)“陷阱”路由,以便预检请求(无授权标头)可以解析请求并获取相应的CORS标头。由于它们不能默认返回中间件200,因此必须在原始请求上添加标头。

2

如果您已经应用了CORS中间件但仍无法正常工作,请尝试以下方法。

如果您的API路由如下:

Route::post("foo", "MyController"})->middleware("cors");

然后您需要更改它以允许OPTIONS方法:
Route::match(['post', 'options'], "foo", "MyController")->middleware("cors");

1

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