Laravel Cors(中间件不工作)

时间:2017-04-14 12:10:03

标签: php laravel

我最近尝试在Laravel 5.4中启用CORS,但不幸的是它并不想工作。我已经包含了它在下面给出的代码和错误。任何人都可以帮助找出它为什么不起作用?我已经通过了所需的标题。

我已将域名重命名为domain.uk,仅用于示例目的,我还没有公开我的网站域名,因为它正在开发中。

路线(制作一条路线::任何用于开发时的测试目的,通常是在生产时它会发布):

Route::group(['domain' => 'api.domain.uk', 'namespace' => 'Api'], function() {
    Route::group(['middleware' => ['cors'], 'prefix' => 'call'], function() {
        Route::get('/rooms/{id}/get-locked-status', 'ApiController@getRoomLockStatus');
        Route::any('/rooms/{id}/update-locked-status', 'ApiController@updateRoomLockStatus');
    });
});

错误:

XMLHttpRequest cannot load http://api.domain.uk/ajax/rooms/1/update-locked-status. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://ice.domain.uk' is therefore not allowed access. The response had HTTP status code 500.

中间件:     

namespace App\Http\Middleware;

use Closure;

class Cors
{
    /**
     * 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')
            ->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
    }
}

的Ajax:

function toggleDoors(roomId) {
    $.ajax({
        url: 'http://api.domain.uk/ajax/rooms/' + roomId + '/update-locked-status',
        type: "POST",
        success: function(data) {
            alert(data);
        }
    });
}

ApiController:

<?php
namespace App\Http\Controllers\Api;

use Auth;
use App\User;
use App\Http\Controllers\Controller;
use Validator;
use Redirect;
use Illuminate\Http\Request;
use App\Database\Frontend\Other\Rooms;

class ApiController extends Controller
{
    public function getRoomLockStatus($id) {
        $room = Rooms::find($id);

        if ($room == null) {
            return response('bad request', 400);
        } 
        else {
            return $room->rp_locked;
        }
    }

    public function updateRoomLockStatus(Request $request, $id) {
        $room = Rooms::find($id);

        if ($room == null) {
            return response('bad request', 400);
        } 

        $room->rp_locked = $room->rp_locked == '1' ? '0' : '1';
        $room->save();

        $responseText = $room->rp_locked == '1' ?
            'Your doors have been locked.' : 'Your doors have been unlocked.';

        return response($responseText, 200);
    }
}

9 个答案:

答案 0 :(得分:6)

请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS#Preflighted_requests_in_CORS

如果您在OPTIONS方法中遇到问题。

内核:: $ routeMiddleware在Laravel 5.4中无法使用请求方法OPTIONS,请参阅https://github.com/laravel/framework/blob/v5.4.0/src/Illuminate/Routing/RouteCollection.php#L214。 要使用CORS中间件,请在Kernel :: $ middleware数组中启用它。这不好,但别无他法。

例如,我使用下一个中间件类用于SPA和API,注意,它不是路由的中间件'cors'

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

/**
 * OptionsCorsResponse middleware - add CORS headers if request method OPTIONS
 */
class OptionsCorsResponse
{
    /**
     *
     * @param Request $request
     * @param Closure $next
     * @return Response
     */
    public function handle($request, Closure $next)
    {
        /* @var $response Response */
        $response = $next($request);
        if (!$request->isMethod('OPTIONS')) {
            return $response;
        }
        $allow = $response->headers->get('Allow'); // true list of allowed methods
        if (!$allow) {
            return $response;
        }
        $headers = [
            'Access-Control-Allow-Methods' => $allow,
            'Access-Control-Max-Age' => 3600,
            'Access-Control-Allow-Headers' => 'X-Requested-With, Origin, X-Csrftoken, Content-Type, Accept',
        ];
        return $response->withHeaders($headers);
    }
}

并在App \ Http \ Kernel

中启用它
protected $middleware = [
    // ...
    \App\Http\Middleware\OptionsCorsResponse::class,
];
  

Origin'http:// ice。域名。因此,不允许英国   访问。响应的HTTP状态代码为500。

调试代码,因为它会产生一些异常。使用任何带有OPTIONS方法的REST客户端。

答案 1 :(得分:3)

您可以通过在bootstrap / app.php中添加标题来轻松实现

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');

答案 2 :(得分:2)

在CORS中,浏览器首先将OPTIONS请求发送到指定的路由。

  

在CORS中,发送带有OPTIONS方法的预检请求,以便服务器可以响应是否可以使用以下参数发送请求:   https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS

所以改变你的中间件:

public function handle($request, Closure $next)
    {
        if ($request->isMethod('OPTIONS')){
            $response = Response::make();
        } else {
            $response = $next($request);
        }
        return $response
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
            ->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
    }

如果您想允许路线使用其他标头,请在'Access-Control-Allow-Headers'标头字段中添加标题。

答案 3 :(得分:1)

如果这些都不起作用,请在apache虚拟主机配置上添加cors(如果使用虚拟主机)。

转到/etc/apache2/sites-available并添加类似this gist

然后sudo a2ensite example.confsudo service apache2 reload;)

答案 4 :(得分:0)

只需在您的路线上添加此代码

header('Access-Control-Allow-Origin: http://yourdomain.com/');

答案 5 :(得分:0)

最近我突然遇到了并非由CORS标头配置引起的CORS问题,我发现了以下内容:

有些Red Herring场景也可能导致显示CORS跨源错误,但与CORS配置没有任何关系。这是由中间件处理CORS并导致其他原因导致触发它的结果。

以下内容可能间接导致错误显示在浏览器响应中:

  • 中间件类中的PHP错误。
  • return $next($request);未在中间件类方法handle中触发。
  • Web或api路由器配置中的
  • Route::middleware引用的中间件已不存在或缺少拼写。
  • 与上述相同,但在控制器中使用$this->middleware();指定了中间件

以上任何一种方法都可以防止Cors中间件被触发,因为该应用退出得太早并且从不设置标头,从而由于中间件文件错误或引用不正确而导致CORS错误而不是500 Server Header错误到中间件。

  

如果确定已正确配置CORS,则应   检查您的PHP错误日志中是否存在中间件错误。

答案 6 :(得分:0)

我在使用withHeaders()方法处理文件时遇到问题,因此,由于以下提示,我想到了这个工作代码:

/**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->isMethod('OPTIONS'))
        {
            return response()->json('{"method":"OPTIONS"}', 200, $headers);
        }

        $response = $next($request);
        $response->headers->set('Access-Control-Expose-Headers', 'Content-Disposition');
        $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:8080','http://localhost','https://edu.pilateswien.org');
        $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');

        //return $response->withHeaders($headers);
        return $response;
    }

答案 7 :(得分:0)

我正在使用Laravel 6及更高版本。该网址帮助我解决了CORS问题:https://medium.com/@petehouston/allow-cors-in-laravel-2b574c51d0c1

使用此代码代替网址中的代码:

<?php

namespace App\Http\Middleware;

use Closure;

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')
              ->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type,X-Token-Auth, Authorization');
    }
}

此外,如果要在整个应用程序中使用中间件,则需要在Kernel.php中进行更改:

protected $middleware = [
\App\Http\Middleware\Cors::class, //add this line to $middleware variable
]

答案 8 :(得分:0)

Sergei 是对的,问题是由于预检请求引起的:https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS#Preflighted_requests_in_CORS

因此,仅向一组端点添加中间件是行不通的,因为预检使用的是 OPTION 方法而不是 GET 方法。

这个 package 正好解决了这个问题,通过在你的内核中为所有路由放置一个中间件,然后你过滤你想要在 CORS 中允许 config/cors.php 的路由. 因此,您还可以处理 option 方法附带的预检请求。

简而言之,安装软件包:

composer require fruitcake/laravel-cors

将中间件放在中间件数组中:

protected $middleware = [
  \Fruitcake\Cors\HandleCors::class,
    // ...
];

发布配置文件:

php artisan vendor:publish --tag="cors"

并在 paths 内的 config/cors 中指定要允许的路由(或仅单个路由):

'paths' => ['api/*'],

另见此blog post了解更多信息。