简体   繁体   English

Symfony 1.4:表单中CSRF的自定义错误消息

[英]Symfony 1.4: Custom error message for CSRF in forms

Can anyone tell me where/how to customise the CSRF token error message for forms in Symfony 1.4. 任何人都可以告诉我在Symfony 1.4中为表单定制CSRF令牌错误消息的位置/方式。 I'm using sfDoctrineGuard for logins and in this form particularly, whenever a session runs out and you still have the page open, it throws a very user-unfriendly error: "CSRF attack detected". 我正在使用sfDoctrineGuard进行登录,特别是在会话用完且你仍然打开页面时,它会抛出一个非常用户不友好的错误:“检测到CSRF攻击”。 Something like "This session has expired. Please return to the home page and try again" sounds better. 类似“此会话已过期。请返回主页再试一次”听起来更好。

What's the right way to do this in the form class? 在表单类中执行此操作的正确方法是什么?

Thanks. 谢谢。

The only way seems to be to overwrite sfForm::addCSRFProtection() . 唯一的方法似乎是覆盖sfForm::addCSRFProtection()

In /lib/form/BaseForm.class.php you can add this piece of code: /lib/form/BaseForm.class.php您可以添加以下代码:

class BaseForm extends sfFormSymfony
{
    public function addCSRFProtection($secret = null)
    {
        parent::addCSRFProtection($secret);
        if (array_key_exists(self::$CSRFFieldName, $this->getValidatorSchema())) {
            $this->getValidator(self::$CSRFFieldName)->setMessage('csrf_attack', 'This session has expired. Please return to the home page and try again.');
        }
    }
}

After calling the parent method, you retrieve the validator associated with the CSRF field and change the message for the code csrf_attack . 在调用父方法之后,检索与CSRF字段关联的验证器,并更改代码csrf_attack的消息。

Edit: You also need to check whether or not the validator exists. 编辑:您还需要检查验证器是否存在。 Some forms might have their CSRF protection disabled! 某些表单可能会禁用其CSRF保护!

Hope this helps! 希望这可以帮助!

None of these answers explain how to remove the "CSRF token:" label that prefixes the error message in a non-hackish way (eg changing the token name is a bad idea!). 这些答案都没有解释如何删除以非hackish方式为错误消息添加前缀的“CSRF令牌:”标签(例如,更改令牌名称是一个坏主意!)。

The only sound way of removing the label is to extend the CSRF validator to throw a global error. 删除标签的唯一合理方法是扩展CSRF验证器以引发全局错误。 While we do this, we can also change the error message. 虽然我们这样做,但我们也可以更改错误消息。

class myValidatorCSRFToken extends sfValidatorCSRFToken
{
  protected function configure($options = array(), $messages = array())
  {
    parent::configure($options, $messages);
    $this->addMessage('csrf_attack', 'Your session has expired. Please return to the home page and try again.');
  }

  protected function doClean($value)
  {
    try {
      return parent::doClean($value);
    } catch (sfValidatorError $e) {
      throw new sfValidatorErrorSchema($this, array($e));
    }
  }
}

Now, let's set our forms to use this validator by overriding sfForm::addCSRFProtection in BaseForm : 现在,让我们来设置我们的形式通过重写使用这个验证sfForm::addCSRFProtectionBaseForm

public function addCSRFProtection($secret = null)
{
  parent::addCSRFProtection($secret);
  if (isset($this->validatorSchema[self::$CSRFFieldName])) //addCSRFProtection doesn't always add a validator
  {
    $this->validatorSchema[self::$CSRFFieldName] = new myValidatorCSRFToken(array(
        'token' => $this->validatorSchema[self::$CSRFFieldName]->getOption('token')
    ));
  }
}

Improving on previous answers, here is the code I use: 改进以前的答案,这是我使用的代码:

public function addCSRFProtection($secret = null)
  {
    parent::addCSRFProtection($secret);
    if (isset($this->validatorSchema[self::$CSRFFieldName])) {
      $this->validatorSchema[self::$CSRFFieldName]->setMessage('csrf_attack', 'This session has expired. Please refresh and try again.');
      $this->getWidgetSchema()->getFormFormatter()->setNamedErrorRowFormatInARow("    <li>%error%</li>\n");
    }
  }

The default value for the NamedErrorRowFormatInARow is "<li>%name%: %error%</li>\\n" adding the name and the colon. NamedErrorRowFormatInARow的默认值是"<li>%name%: %error%</li>\\n"添加名称和冒号。 Be careful because it changes the value for all forms and all global errors. 要小心,因为它会更改所有表单和所有全局错误的值。

You can also change the field by creating a custom form formatter and using it in the forms you want. 您还可以通过创建自定义表单格式化程序并在所需的表单中使用它来更改字段。 You can go look at the documentation here for more info on this. 您可以在此处查看文档以获取更多相关信息。

In 1.4.4 I had to modify naag's code like so... 在1.4.4中,我不得不像这样修改naag的代码......

public function addCSRFProtection($secret = null)
{
  parent::addCSRFProtection($secret);
  if (isset($this->validatorSchema[self::$CSRFFieldName])) {
    $this->validatorSchema[self::$CSRFFieldName]->setMessage('csrf_attack', 'This session has expired. Please refresh and try again.');
  }
}

This got it working, the 'csrf token:' bit still appears in the error message though. 这使它工作,'csrf令牌:'位仍然出现在错误消息中。

Use event dispatcher. 使用事件调度程序。 Check this out http://bluehorn.co.nz/2010/07/15/how-to-change-csrf-attack-message-in-symfony-1-2/ 看看这个http://bluehorn.co.nz/2010/07/15/how-to-change-csrf-attack-message-in-symfony-1-2/

I wrote it for Symfony 1.2, but using event dispatcher, so it still might work for Symfony 1.4. 我为Symfony 1.2编写了它,但是使用事件调度程序,所以它仍然适用于Symfony 1.4。

我想通过设置CSRF令牌字段的标签,当然可以全局删除或自定义“csrf token:”前缀。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM