Laravel 5.2 CORS, GET не работает с предполетными вариантами

Страшная ошибка CORS:

Запрос на перекрестный запрос заблокирован: политика одинакового происхождения запрещает чтение удаленный ресурс в http://localhost/mysite/api/test. (Причина: CORS заголовок 'Access-Control-Allow-Origin' отсутствует.

Маршрут Laravel:

$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router) {
    $router->get('/test', '[email protected]');
});

Laravel Cors Middlware:

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::make('OK', 200, $headers);
        }

        $response = $next($request);
        foreach ($headers as $key => $value)
            $response->header($key, $value);
        return $response;
    }

Ядро Laravel:

 protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'cors' => \App\Http\Middleware\CORS::class
    ];

Релевантный .htaccess:

RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Релевантный Vue.js:

 new Vue({
        el: '#app',
        data: {
           //data here
        },
        http: {
            headers: {
                "Authorization": "Basic " + "apiKeyHere"
            }
        },
        methods: {
            mymethod: function (e)
            {
                e.preventDefault();
                this.$http.get('http://localhost/mysite/api/test').then(
                        function (response)
                        {
                          //do something
                        }
                )
            }
        }
    });

Если я выберу параметр заголовка авторизации, запрос будет выполнен.

Я также пробовал https://github.com/barryvdh/laravel-cors, но до сих пор не радуюсь. Любая помощь ценится!

Ответ 1

Ясно, что это идеальное решение, но оно РАБОТАЕТ. Я добавил это в начало моего файла routes.php:

header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );

Было бы неплохо заставить это работать без взлома... увы.

ОБНОВЛЕНИЕ: Оказалось, что это связано с IIS. Я закончил настройку заголовков в файле web.config, и теперь CORS работает без взлома файла route.php.

<httpProtocol>
    <customHeaders>
       <add name="Access-Control-Allow-Headers" value="Origin, Authorization, X-Requested-With, Content-Type, Accept" />
       <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
    </customHeaders>
</httpProtocol>

Если вы хотите ограничить доступ, вы можете добавить исходящие правила:

      <outboundRules>
          <clear />
                <rule name="AddCrossDomainHeader">
                    <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                        <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?somesite\.com|(.+\.)?anothersite\.org))" />
                    </conditions>
                    <action type="Rewrite" value="{C:0}" />
                </rule>
      </outboundRules>

Ответ 2

Я решаю свою проблему, просто добавив эти строки в мойways.php Laravel 5.2 Для более чем 5.2 в маршрутах /web.php

header('Access-Control-Allow-Origin:  *');
header('Access-Control-Allow-Methods:  POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers:  Content-Type, X-Auth-Token, Origin, Authorization');

ИЛИ зарегистрируйте промежуточное ПО Cors в глобальном стеке промежуточного ПО HTTP

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \App\Http\Middleware\CorsMiddleware::class
];

Ответ 3

Ваше промежуточное программное обеспечение в порядке, но вам необходимо зарегистрировать промежуточное ПО Cors в глобальном стеке промежуточного программного обеспечения HTTP.

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \App\Http\Middleware\CorsMiddleware::class
];

Ответ 4

Проблема возникает из предпродажного запроса, действительно, но способ обработки требует некоторого дополнительного объяснения, когда мы говорим о Laravel - в основном запрос OPTIONS маршрутизируется (что-то другое скорее напоминает PHP-путь, чем Laravel путь), поэтому вам нужно добавить это к вашим маршрутам, чтобы они были успешными:

Route::options('/{any}', function(){ return ''; })->where('any', '.*');

Теперь позвольте использовать все другие методы - создайте промежуточное ПО CORS:

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, PATCH, PUT, DELETE');
    }
}

И, наконец, для данного маршрута используйте это промежуточное ПО:

Route::put('/test', function(){ echo('test'); })->with('cors');

Ответ 5

Вы можете обойти это без использования какого-либо промежуточного программного обеспечения, такого как Barryvdh\Cors для Laravel, который не работал должным образом с JWT AUTH, я добавил следующие инструкции в index.php в Laravel непосредственно перед экземпляром ядра

header('Access-Control-Allow-Origin: http://localhost:8001');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token,Authorization');
header('Access-Control-Allow-Credentials: true');

добавить это до

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

это также должно работать с JWT AUTH. Обратите внимание, что в Access-Control-Allow-Headers вы должны включить авторизацию, иначе ваш accesstoken не будет разрешен с заголовком авторизации, поэтому JWT AUTH не удастся. Счастливое кодирование.

Ответ 6

Мое решение:

$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router){
    $router->options('{param1?}/{param2?}/{param3?}', function () {});
});

Ответ 7

Этот ответ основан на этой статье. Библиотека промежуточного программного обеспечения barryvdh/laravel-cors, может использоваться для решения проблемы (Cross-Origin Resource Sharing).

Шаг 1 Установите его:

composer require barryvdh/laravel-cors

Шаг 2 Выпуск вендорских файлов библиотеки:

php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"

шаг 3 Команда, запущенная на шаге 2, скопирует файл cors.php в каталог конфигурации, который выглядит следующим образом:

return [

/*
|--------------------------------------------------------------------------
| Laravel CORS
|--------------------------------------------------------------------------
|
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
| to accept any value.
|
*/

'supportsCredentials' => false,
'allowedOrigins' => ['*'],// ex: ['abc.com', 'api.abc.com']
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'],// ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,

];

Для allowedOrigins значение может быть либо ['*'] которое указывает, что источником запроса может быть любой домен, либо массивом определенных доменов, которые могут быть источниками, которым мы позволим отправлять запрос в наши api, например, так ['first.com', 'second.com', 'register.third.com']

а также allowedMethods может быть ['*'] или списком разрешенных HTTP verbs например ['POST', 'GET']

Шаг 4 Регистрация промежуточного программного обеспечения Cors. Откройте app/Http/kernel.php и добавьте класс HandleCors в $routeMiddleware следующим образом:

protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'cors' => \Barryvdh\Cors\HandleCors::class, // add this line to enable cors to your routes
];

Шаг 5 Теперь вы можете добавить промежуточное программное обеспечение laravel-cors к любому маршруту, который вы хотите. Например, в Routes/api.php я сделаю это:

Route::apiResource('category', 'CategoryController')->middleware('cors');
Route::apiResource('product', 'ProductController')->middleware('cors');