Commit 6dc056b3 by Philippe Gaultier Committed by Alexander Makarov

#4388: CORS filter fixes:

- Upgrade the documentation to match filter code - Fix bad default behavior with Access-Control-Allow-Credentials - Fix missing "s" in header Access-Control-Request-Method / Access-Control-Allow-Methods
parent e486b663
...@@ -346,10 +346,10 @@ The Cors filtering could be tuned using the `cors` property. ...@@ -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['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-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-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`. * `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 ```php
use yii\filters\Cors; use yii\filters\Cors;
...@@ -363,7 +363,6 @@ public function behaviors() ...@@ -363,7 +363,6 @@ public function behaviors()
'cors' => [ 'cors' => [
'Origin' => ['http://www.myserver.net'], 'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'], 'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
'Access-Control-Allow-Credentials' => null,
], ],
], ],
], parent::behaviors()); ], parent::behaviors());
...@@ -385,7 +384,6 @@ public function behaviors() ...@@ -385,7 +384,6 @@ public function behaviors()
'cors' => [ 'cors' => [
'Origin' => ['http://www.myserver.net'], 'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'], 'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
'Access-Control-Allow-Credentials' => null,
], ],
'actions' => [ 'actions' => [
'login' => [ 'login' => [
......
...@@ -79,7 +79,7 @@ class Cors extends ActionFilter ...@@ -79,7 +79,7 @@ class Cors extends ActionFilter
'Origin' => ['*'], 'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'], 'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true, 'Access-Control-Allow-Credentials' => null,
'Access-Control-Max-Age' => 86400, 'Access-Control-Max-Age' => 86400,
]; ];
...@@ -151,14 +151,19 @@ class Cors extends ActionFilter ...@@ -151,14 +151,19 @@ class Cors extends ActionFilter
} }
} }
$this->prepareAllowHeaders('Method', $requestHeaders, $responseHeaders);
$this->prepareAllowHeaders('Headers', $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) { if ($this->cors['Access-Control-Allow-Credentials'] === true) {
$responseHeaders['Access-Control-Allow-Credentials'] = 'true'; $responseHeaders['Access-Control-Allow-Credentials'] = 'true';
} elseif ($this->cors['Access-Control-Allow-Credentials'] === false) { } elseif ($this->cors['Access-Control-Allow-Credentials'] === false) {
$responseHeaders['Access-Control-Allow-Credentials'] = 'false'; $responseHeaders['Access-Control-Allow-Credentials'] = 'false';
} }
if (($_SERVER['REQUEST_METHOD'] === 'OPTIONS') && ($this->cors['Access-Control-Max-Age'] !== null)) { if (($_SERVER['REQUEST_METHOD'] === 'OPTIONS') && ($this->cors['Access-Control-Max-Age'] !== null)) {
$responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age']; $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age'];
} }
...@@ -178,20 +183,12 @@ class Cors extends ActionFilter ...@@ -178,20 +183,12 @@ class Cors extends ActionFilter
$responseHeaderField = 'Access-Control-Allow-'.$type; $responseHeaderField = 'Access-Control-Allow-'.$type;
if (isset($requestHeaders[$requestHeaderField])) { if (isset($requestHeaders[$requestHeaderField])) {
if (in_array('*', $this->cors[$requestHeaderField])) { if (in_array('*', $this->cors[$requestHeaderField])) {
if ($type === 'Method') { $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]);
$responseHeaders[$responseHeaderField] = strtoupper($requestHeaders[$requestHeaderField]);
} elseif ($type === 'Headers') {
$responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]);
}
} else { } else {
$requestedData = preg_split("/[\s,]+/", $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY); $requestedData = preg_split("/[\s,]+/", $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY);
$acceptedData = []; $acceptedData = [];
foreach ($requestedData as $req) { foreach ($requestedData as $req) {
if ($type === 'Method') { $req = $this->headerize($req);
$req = strtoupper($req);
} elseif ($type === 'Headers') {
$req = $this->headerize($req);
}
if (in_array($req, $this->cors[$requestHeaderField])) { if (in_array($req, $this->cors[$requestHeaderField])) {
$acceptedData[] = $req; $acceptedData[] = $req;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment