Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement CSRF tokens ? #4

Open
dadinugroho opened this issue Apr 5, 2014 · 4 comments
Open

How to implement CSRF tokens ? #4

dadinugroho opened this issue Apr 5, 2014 · 4 comments

Comments

@dadinugroho
Copy link

When we enable csrf, the error will appear "The CSRF token could not be verified". Where we can add the parameter for csrf?

@dadinugroho
Copy link
Author

My current workaround is to introduce new variable called csrfToken.

my admin.php where the GridView is defined:

array('name' => 'barcode',
            'class' => 'EEditableColumn', 'editable_type' => 'editbox', 'csrfToken' => Yii::app()->request->csrfToken,
            'action' => array('/product/ajaxEditColumn'),
        ),

In EEditableColumn.php

...
    public $csrfToken;
    public $editable_type;  // "editbox","select" (required array in editable_options)
    public $editable_options; // array(1=>'yes',0=>'no')
    public $action;    // the action receptor when receiving changes. 

    //  array('someaction')

    public function renderDataCell($row) {
        $dummy = new EEditable($this->grid->id);
        $data = $this->grid->dataProvider->data[$row];
        $options = $this->htmlOptions;
        if ($this->cssClassExpression !== null) {
            $class = $this->evaluateExpression($this->cssClassExpression, array('row' => $row, 'data' => $data));
            if (!empty($class)) {
                if (isset($options['class']))
                    $options['class'].=' ' . $class;
                else
                    $options['class'] = $class;
            }
        }
        if (null != $this->editable_type) {
            $options['editable_type'] = $this->editable_type;
            $options['editable_name'] = $this->name;
            $keyValue = "0";
            if (isset($this->grid->dataProvider->keyField)) {
                $dpKeyField = $this->grid->dataProvider->keyField;
                if (!isset($data[$dpKeyField]))
                    throw new Exception("The provided keyField '$dpKeyField' "
                    . "is not defined in your data columns or array indexes");
                $keyValue = $data[$dpKeyField];
            }else {
                $keyValue = $data->primarykey;
            }
            $options['editable_action'] = CHtml::normalizeUrl($this->action);
            $options['editable_id'] = $keyValue;
            $options['editable_csrf'] = $this->csrfToken;
        }
        echo CHtml::openTag('td', $options);
...

In eeditable.js,

...
 if ((new_value != null) && (new_value != saved_value)) {
            tag.find('input').attr('disabled', 'disabled');
            $.ajax({
                url: tag.attr('editable_action'), type: 'post',
                data: {"YII_CSRF_TOKEN": tag.attr('editable_csrf'), keyvalue: _getKeyValue(tag),
                    name: _getKeyName(tag), old_value: saved_value,
                    new_value: new_value},
                success: function(response) {
                    tag.data('eeditablegrid_value', response);
                    _reset(tag);
                    tag.find('input').attr('disabled', null);
                },
...

That's what I have been done to make it work. But, I hope you can find better and more simple solution.

Cheers,

Daniel

@christiansalazar
Copy link
Owner

thank u very much. reading your post carefully.

@christiansalazar
Copy link
Owner

Your solution is nicely implemented. Looking ahead in the base-base class: http://www.yiiframework.com/doc/api/1.1/CGridColumn#htmlOptions-detail you'll find the htmlOptions attribute, using that attribute you can skeep the code change at EEditableColumn by simply providing the token in:

[php]
array('name' => 'barcode',
            'class' => 'EEditableColumn', 'editable_type' => 'editbox', 

            // instead of:
            // 'csrfToken' => Yii::app()->request->csrfToken, 
           // do it in this way:
           'htmlOptions'=>array('csrfToken' => Yii::app()->request->csrfToken,),

            'action' => array('/product/ajaxEditColumn'),
        ),

the next change required is that made by you in the assets/eeditable.js:

[javascript]
...
 if ((new_value != null) && (new_value != saved_value)) {
            tag.find('input').attr('disabled', 'disabled');
            $.ajax({
                url: tag.attr('editable_action'), type: 'post',
                data: {"YII_CSRF_TOKEN": tag.attr('editable_csrf'), keyvalue: _getKeyValue(tag),
                    name: _getKeyName(tag), old_value: saved_value,
                    new_value: new_value},
                success: function(response) {
                    tag.data('eeditablegrid_value', response);
                    _reset(tag);
                    tag.find('input').attr('disabled', null);
                },
...

maybe later i can implement options available for this ajax call,

christiansalazar added a commit that referenced this issue Apr 5, 2014
@christiansalazar christiansalazar changed the title Csrf error How to implement CSRF tokens ? Apr 5, 2014
@dadinugroho
Copy link
Author

Googling on this topic, there is a suggestion to add a CActiveForm to enclose the input and in ajax call we only need to serialize the form. Hence, if we enable csrf, the CActiveForm will add the csrf token into a hidden field. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants