Browse Source

Supports sending CSRF token via HTTP header.

tags/2.0.0-beta
Qiang Xue 11 years ago
parent
commit
2deff126cf
  1. 26
      framework/yii/web/Request.php

26
framework/yii/web/Request.php

@ -68,19 +68,28 @@ use yii\helpers\Security;
class Request extends \yii\base\Request class Request extends \yii\base\Request
{ {
/** /**
* The name of the HTTP header for sending CSRF token.
*/
const CSRF_HEADER = 'X-CSRF-TOKEN';
/**
* @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false. * @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false.
* By setting this property to true, forms submitted to an Yii Web application must be originated * When CSRF validation is enabled, forms submitted to an Yii Web application must be originated
* from the same application. If not, a 400 HTTP exception will be raised. * from the same application. If not, a 400 HTTP exception will be raised.
* *
* Note, this feature requires that the user client accepts cookie. Also, to use this feature, * Note, this feature requires that the user client accepts cookie. Also, to use this feature,
* forms submitted via POST method must contain a hidden input whose name is specified by [[csrfVar]]. * forms submitted via POST method must contain a hidden input whose name is specified by [[csrfVar]].
* You may use [[\yii\web\Html::beginForm()]] to generate his hidden input. * You may use [[\yii\web\Html::beginForm()]] to generate his hidden input.
*
* In JavaScript, you may get the values of [[csrfVar]] and [[csrfToken]] via `yii.getCsrfVar()` and
* `yii.getCsrfToken()`, respectively. The [[\yii\web\YiiAsset]] asset must be registered.
*
* @see http://en.wikipedia.org/wiki/Cross-site_request_forgery * @see http://en.wikipedia.org/wiki/Cross-site_request_forgery
*/ */
public $enableCsrfValidation = false; public $enableCsrfValidation = false;
/** /**
* @var string the name of the token used to prevent CSRF. Defaults to '_csrf'. * @var string the name of the token used to prevent CSRF. Defaults to '_csrf'.
* This property is effectively only when [[enableCsrfValidation]] is true. * This property is used only when [[enableCsrfValidation]] is true.
*/ */
public $csrfVar = '_csrf'; public $csrfVar = '_csrf';
/** /**
@ -986,6 +995,14 @@ class Request extends \yii\base\Request
} }
/** /**
* @return string the CSRF token sent via [[CSRF_HEADER]] by browser. Null is returned if no such header is sent.
*/
public function getCsrfTokenFromHeader()
{
return isset($_SERVER[self::CSRF_HEADER]) ? $_SERVER[self::CSRF_HEADER] : null;
}
/**
* Creates a cookie with a randomly generated CSRF token. * Creates a cookie with a randomly generated CSRF token.
* Initial values specified in [[csrfCookie]] will be applied to the generated cookie. * Initial values specified in [[csrfCookie]] will be applied to the generated cookie.
* @return Cookie the generated cookie * @return Cookie the generated cookie
@ -1012,7 +1029,7 @@ class Request extends \yii\base\Request
} }
$method = $this->getMethod(); $method = $this->getMethod();
if ($method === 'POST' || $method === 'PUT' || $method === 'PATCH' || $method === 'DELETE') { if ($method === 'POST' || $method === 'PUT' || $method === 'PATCH' || $method === 'DELETE') {
$cookies = $this->getCookies(); $trueToken = $this->getCookies()->getValue($this->csrfVar);
switch ($method) { switch ($method) {
case 'POST': case 'POST':
$token = $this->getPost($this->csrfVar); $token = $this->getPost($this->csrfVar);
@ -1027,7 +1044,8 @@ class Request extends \yii\base\Request
$token = $this->getDelete($this->csrfVar); $token = $this->getDelete($this->csrfVar);
} }
if (empty($token) || $cookies->getValue($this->csrfVar) !== $token) { $valid = !empty($token) && $token === $trueToken || $this->getCsrfTokenFromHeader() === $trueToken;
if (!$valid) {
throw new HttpException(400, Yii::t('yii', 'Unable to verify your data submission.')); throw new HttpException(400, Yii::t('yii', 'Unable to verify your data submission.'));
} }
} }

Loading…
Cancel
Save