Friday, March 16, 2012

AJAX and Cross Site Request Forgery

One of Yii's features is Cross Site Request Forgery protection. This is mostly transparent and happening automatically if enabled in protected/config/main.php, the relevant option is:

<?php
    //...
    'components'=>array(
        'request'=>array(
            'enableCsrfValidation'=>true,
        ),
    ),
    //...

On each request it then generates a new token which is transparently included in all forms generated by CHtml::beginForm. Checking this token is also handled transparently on submission of these forms.

However, if you are doing AJAX requests, you'll have to pass the token manually. In practice, this is easily overlooked, and leads to irritating bug searches. Since Yii by default uses jQuery and jQuery supports setting default AJAX options, this is how AJAX requests can include the CSRF token automatically (in protected/components/Controller.php):

<?php
class Controller extends CController
{
    public function init()
    {
        $this->initAjaxCsrfToken();
    }
    protected function initAjaxCsrfToken()
    {
        Yii::app()->clientScript->registerScript('AjaxCsrfToken',
        'jQuery.ajaxOptions({data:' . json_encode(array(
            Yii::app()->request->csrfTokenName => Yii::app()->request->csrfToken,
        )) .'});', CClientScript::POS_HEAD);
    }
}

That's it, from now on all AJAX requests done using jQuery include the CSRF token. This includes requests done using $.ajax, $.get, $.post, $.load and others since they all fallback to using $.ajax.

No comments:

Post a Comment