diff --git a/docs/guide/structure-filters.md b/docs/guide/structure-filters.md index c1101bab30..af17ae07a7 100644 --- a/docs/guide/structure-filters.md +++ b/docs/guide/structure-filters.md @@ -346,10 +346,10 @@ The Cors filtering could be tuned using the `cors` property. * `cors['Origin']`: array used to define allowed origins. Can be `['*']` (everyone) or `['http://www.myserver.net', 'http://www.myotherserver.com']`. Default to `['*']`. * `cors['Access-Control-Request-Method']`: array of allowed verbs like `['GET', 'OPTIONS', 'HEAD']`. Default to `['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']`. * `cors['Access-Control-Request-Headers']`: array of allowed headers. Can be `['*']` all headers or specific ones `['X-Request-With']`. Default to `['*']`. -* `cors['Access-Control-Allow-Credentials']`: define if current request can be made using credentials. Can be `true`, `false`. Default to `true`. +* `cors['Access-Control-Allow-Credentials']`: define if current request can be made using credentials. Can be `true`, `false` or `null` (not set). Default to `null`. * `cors['Access-Control-Max-Age']`: define lifetime of pre-flight request. Default to `86400`. -For example, allowing CORS for origin : `http://www.myserver.net` with method `GET`, `HEAD` and `OPTIONS` and do not send `Access-Control-Allow-Credentials` header : +For example, allowing CORS for origin : `http://www.myserver.net` with method `GET`, `HEAD` and `OPTIONS` : ```php use yii\filters\Cors; @@ -363,7 +363,6 @@ public function behaviors() 'cors' => [ 'Origin' => ['http://www.myserver.net'], 'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'], - 'Access-Control-Allow-Credentials' => null, ], ], ], parent::behaviors()); @@ -385,7 +384,6 @@ public function behaviors() 'cors' => [ 'Origin' => ['http://www.myserver.net'], 'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'], - 'Access-Control-Allow-Credentials' => null, ], 'actions' => [ 'login' => [ diff --git a/framework/filters/Cors.php b/framework/filters/Cors.php index b5698881a1..1d0fbe823a 100644 --- a/framework/filters/Cors.php +++ b/framework/filters/Cors.php @@ -79,7 +79,7 @@ class Cors extends ActionFilter 'Origin' => ['*'], 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], 'Access-Control-Request-Headers' => ['*'], - 'Access-Control-Allow-Credentials' => true, + 'Access-Control-Allow-Credentials' => null, 'Access-Control-Max-Age' => 86400, ]; @@ -151,14 +151,19 @@ class Cors extends ActionFilter } } - $this->prepareAllowHeaders('Method', $requestHeaders, $responseHeaders); + $this->prepareAllowHeaders('Headers', $requestHeaders, $responseHeaders); + if (isset($requestHeaders['Access-Control-Request-Method'])) { + $responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']); + } + if ($this->cors['Access-Control-Allow-Credentials'] === true) { $responseHeaders['Access-Control-Allow-Credentials'] = 'true'; } elseif ($this->cors['Access-Control-Allow-Credentials'] === false) { $responseHeaders['Access-Control-Allow-Credentials'] = 'false'; } + if (($_SERVER['REQUEST_METHOD'] === 'OPTIONS') && ($this->cors['Access-Control-Max-Age'] !== null)) { $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age']; } @@ -178,20 +183,12 @@ class Cors extends ActionFilter $responseHeaderField = 'Access-Control-Allow-'.$type; if (isset($requestHeaders[$requestHeaderField])) { if (in_array('*', $this->cors[$requestHeaderField])) { - if ($type === 'Method') { - $responseHeaders[$responseHeaderField] = strtoupper($requestHeaders[$requestHeaderField]); - } elseif ($type === 'Headers') { - $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]); - } + $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]); } else { $requestedData = preg_split("/[\s,]+/", $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY); $acceptedData = []; foreach ($requestedData as $req) { - if ($type === 'Method') { - $req = strtoupper($req); - } elseif ($type === 'Headers') { - $req = $this->headerize($req); - } + $req = $this->headerize($req); if (in_array($req, $this->cors[$requestHeaderField])) { $acceptedData[] = $req; }