Php Laravel 5.2 CORS,无法使用飞行前选项

Php Laravel 5.2 CORS,无法使用飞行前选项,php,laravel,cors,vue.js,laravel-5.2,Php,Laravel,Cors,Vue.js,Laravel 5.2,可怕的CORS错误: 已阻止跨源请求:同一源策略不允许读取 位于的远程资源。(理由:CORS 缺少标题“访问控制允许原点”) 拉维尔路线: $router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router) { $router->get('/test', 'MyController@myMethod'); }); Laravel Cors Middlware: public

可怕的CORS错误:

已阻止跨源请求:同一源策略不允许读取 位于的远程资源。(理由:CORS 缺少标题“访问控制允许原点”)

拉维尔路线:

$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内核:

 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
    ];
相关.访问:

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
                        }
                )
            }
        }
    });
如果我去掉Authorization header选项,请求就会生效

我也试过了,但还是没有乐趣。
感谢您的帮助

显然不是理想的解决方案,但确实有效。我已将此添加到routes.php文件的顶部:

header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
这将是很好的工作没有黑客。。。唉

更新:结果是与IIS有关。我最终在web.config文件中设置了标题,现在CORS可以在不破坏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>

如果要限制访问,可以添加出站规则:

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

我解决了我的问题,只需在我的routes上添加这些行。php Laravel 5.2 对于routes/web.php中大于5.2的

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');
或者在全局HTTP中间件堆栈中注册Cors中间件

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

您的中间件还可以,但需要在全局HTTP中间件堆栈中注册Cors中间件

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

您无需使用任何中间件(如Barryvdh\Cors for Laravel)就可以绕过这个问题,因为它无法与JWT AUTH正常工作。在内核实例化之前,我在Laravel的index.php中添加了以下语句

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标头中,您应该包括授权,否则您的accesstoken将不被授权标头所允许,因此JWT AUTH将失败。快乐编码。

问题确实是由飞行前请求引起的,但处理方式需要一些额外的解释,当我们谈论Laravel时,主要是
选项
请求被路由(其他答案是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');
    }
}
最后,对于给定的路由,使用该中间件:

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

此答案基于此。 中间件库,可用于解决问题(跨源资源共享)

步骤1安装:

composer require barryvdh/laravel-cors
步骤2发布库的供应商文件:

php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
步骤3步骤2中运行的命令将cors.php文件复制到config目录,如下所示:

对于
allowedOrigins
而言,该值可以是
['*']
,表示请求的来源可以来自任何域,也可以是特定域的数组,这些域可以是我们将允许向
api发送请求的来源,如
['first.com','second.com','register.third.com']

而且
允许的方法
可以是
['*']
或允许的
HTTP动词列表
,例如
['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');
我的解决方案:

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

即使将您的中间件直接放入
$middleware
而不是
$routeMiddleware
,或者只是在app.php中全局定义头文件,这也是一个可怕的决定,因为它将使用新的CORS策略公开所有端点,如果您只想向第三方解决方案公开API的一部分

更好的解决方案是只允许在所有端点上进行选项调用,并且仍然通过
$routeMiddleware
重定向其他HTTP方法,以便能够将CORS策略仅限制在端点的子集上

因此,构建两个中间件:

Cors.php


您是否看到控制台中显示了多个请求(飞行前以及实际的请求)?是的,我看到了两个请求。请确保,您已经使用正确的
cors
密钥在
Kernel.php
中注册了中间件?您解决了这个问题吗?这可能重复,不允许任何人在没有身份验证的情况下向我们的API发出请求吗?@plushyObject我刚刚更新了我的答案以解决您的问题。您将这些问题确切地放在web.config中的什么位置?我在追他们,但没用。另外,我没有使用IIS,我使用的是docker/nginx,我还需要这样做吗?你的
模式对我不起作用,我使用了这个:
(https://right\.example\.com|https://left\.example\.com)
对某些情况很有帮助。。但测试将失败。但仍然不是最好的选择+1@tam5是的,测试失败了。有没有关于如何正确修复它的建议?@HiradRoshandel我想我所做的是在中间件中封装头文件,然后在没有它的情况下运行测试,但我记不太清楚了,,,等我有时间找到我想要的东西时,我会再联系你did@tam5啊,我明白了!我尝试了Utwo的答案,它解决了“生命储蓄”的问题!我是用全球CORS中间件完成的。通常,对于测试问题,我会通过检查
if(!\App::environment('testing')
进行筛选,以避免出现问题。直到我将其添加到全局中间件空间,它才起作用。感谢您保存meSo,它被称为“飞行前请求”:)谢谢!路由::选项(。。。