web-dev-qa-db-fra.com

Laravel 5.2 CORS, GET ne fonctionne pas avec les OPTIONS de contrôle en amont

L'erreur redoutée de CORS:

Demande d'origine croisée bloquée: la même politique d'origine interdit la lecture de la ressource distante à http: // localhost/mysite/api/test . (Raison: en-tête CORS 'Access-Control-Allow-Origin' manquant).

Itinéraire Laravel:

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

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 Kernel:

 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 pertinent:

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

Vue.js pertinente:

 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
                        }
                )
            }
        }
    });

Si je retire l'option d'en-tête Autorisation, la demande fonctionne.

J'ai également essayé https://github.com/barryvdh/laravel-cors mais toujours pas de joie. Toute aide appréciée!

22
suncoastkid

Ce n'est clairement pas la solution idéale, mais cela FONCTIONNE. J'ai ajouté ceci en haut de mon fichier routes.php:

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

Ce serait bien de faire fonctionner ça sans hack ... hélas.

MISE À JOUR: Il s'est avéré être IIS lié. J'ai fini par définir les en-têtes dans le fichier web.config et maintenant CORS fonctionne sans pirater le fichier routes.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>

Si vous souhaitez restreindre l'accès, vous pouvez ajouter des règles sortantes:

      <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>
24
suncoastkid

Je résout mon problème en ajoutant simplement ces lignes sur mes routes.php Laravel 5.2 Pour plus de 5.2 dans routes/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');

OU enregistrez le middleware Cors dans la pile globale de middleware HTTP

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

Votre middleware est correct mais vous devez enregistrer le middleware Cors dans la pile globale de middleware HTTP.

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

Le problème découle de la demande de contrôle en amont, en effet, mais la façon de gérer nécessite quelques explications supplémentaires, lorsque nous parlons de Laravel - principalement OPTIONS la demande est routée (quelque chose que d'autres réponses font plutôt PHP way, que Laravel way), donc, vous devez l'ajouter à vos itinéraires pour qu'il soit réussi:

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

Maintenant, traitons toutes les autres méthodes - créez le middleware 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');
    }
}

Et enfin, pour un itinéraire donné, utilisez ce middleware:

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

5
eithed

Vous pouvez contourner celui-ci sans utiliser de middleware comme Barryvdh\Cors pour Laravel qui ne fonctionnait pas correctement avec JWT AUTH, j'ai ajouté les instructions suivantes dans index.php dans Laravel juste avant l'instanciation du noyau

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');

ajoutez celui-ci avant

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

cela devrait également fonctionner correctement avec JWT AUTH. Veuillez noter que dans Access-Control-Allow-Headers, vous devez inclure Authorization sinon votre accesstoken ne sera pas autorisé avec l'en-tête Authorization, donc JWT AUTH échouera. Codage heureux.

3
SOUMYA

Ma solution:

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