"safe" and "unsafe" Model validators (massive assignments)

7 followers

This wiki article has not been tagged with a corresponding Yii version yet.
Help us improve the wiki by updating the version information.

Ok, it is a little bit difficult to full understanding the unsafe validator.

User inputs that have not at least one validator in model will be rejected

So why the 'unsafe' validator is useful and when ?

Suppose You have an attribute in Model (CActiveRecord) that has to be saved (in most cases)

So the rule for this attribute should be

array('text_user_input', 'safe'), //or any other usual validator

Suppose also you have a blacklist users whom you want to prevent to pass their inputs. How to achieve that? A solution is using the unsafe validator

array('text_user_input', 'unsafe', 'on'=>'blacklistuser'),

I give you an example with code to make it cleaner

model:

class Article extends CActiveRecord {
...
array('text_user_input', 'safe'),
array('text_user_input', 'unsafe', 'on'=>'blacklistuser'),
...
}

viewer: //nothing extra, gii generated all the stuffs

controller:

public function actionNewArticle() {
       if (Yii::app()->user->id == '13' ) { //as example
          $model = new Article('blacklistuser');
          $isblacklist = true;
      } else {
        $model = new Article;
        $isblacklist = false;
     }
 
if (isset($_POST['Article'])) {
    $model->attributes = $_POST['Article'];
    if ($model->validate()) {
       $model->save(false)
    } else {
        if ($isblacklist) $model->addError('text_user_input','Are you an ambitious hacker eh?');
    }
}
 
     $this->render('create',array('model'=>$model));
 }

note: the first rule matches and save the attribute (for all cases even for blacklistuser scenario) but the second one overrides the first and assigns as unsaved this attribute. also Îșeep in mind the order of the rules is irrelevant.

Total 2 comments

#14056 report it
DiS at 2013/07/15 09:11pm
It is an extremely ugly code style

Never use this example in real life.

  1. Model should not have two scenarios for this case. What will happen if I will have to deal with two parameters? Let's say, blacklisted user and special type of post, it will be 4 scenarios? Create property in the model, set it according to conditions.
  2. Based on that property dynamically add validator, use events to attach it $validators = $this->getValidatorList(); $validators->add(CValidator::createValidator('unsafe', $this, 'text_user_input', array('on' => 'blablabla')));
  3. Handle errors inside the model, not in Controller, it is not it's responsibility. Use events here too.
#14048 report it
redguy at 2013/07/15 10:17am
this article is far from real explanation of safe/unsafe...

...first of all - all validators can be safe and unsafe. you can control it with 'safe' attribute, like:

...
  array( 'email_field', 'email', 'safe'=>false ),
  ...

'safe' and 'unsafe' VALIDATORS are just empty validators that already have this attribute set to true/false respectively. And now - what is the point of this attribute? You must imagine that rule() function which returns 'validators' is in fact called at least in two scenarios (not the Yii AR 'scenarios', but scenarios in general :) ):

  • massive assignments
  • validation

they have much in common, so they are handled with this one function. Massive assignment is when you do:

$model->attributes = $_POST['Model'];

which assigns ALL attributes passed with POST array to proper $model attribute. It is assumed that massive assignment is secure only when there are validators for attribute, because they can somehow check if provided value is correct. This is why rules() method is used in massive assignment. But rules() are also required to do validation before saving model to database for example. There are situations when you want validators that will check attribute value before saving it to database, but you do not want to expose such attribute for massive assignments for security reasons - this is when 'usafe' is handy. You can add 'usafe' validator for such attribute or mark validators for this field with 'safe'=>false. The result will be exactly the same. 'safe' validator on the other hand is used when you want to expose attribute for massive assignment but you do not care what value is passed (no other validation). It should be used with care as it may lead to vulnerabilities and security holes. Instead you should consider any other validator that will check passed value with 'safe'=>true flag.

Leave a comment

Please to leave your comment.

Write new article