Security in Yii

Reading this wiki: http://www.yiiframework.com/wiki/250/yii-for-beginners/

I found this section:


  1. Security

There is one thing I would like to show you. It is very simple, but I didn’t realize this security error for quite a long time.

Imagine that you are creating an administration for a forum. If a user loges in, he can edit his posts. Not posts of other people. First, he’s presented with list of his posts. You surely filter them by “id_user” that is stored in session. If user clicks an item of this list, he will see details of this post and he can change it. This is done using hidden form field with id_post. But I didn’t know that it was so easy to change the value of this hidden field.

To filter posts by id_user I recommend creating a scope in Post model that will return only posts of logged user. Scope can work with the session variable id_user. This scope can be named getCurrentUsersPosts. Filtering than looks like this:




$posts = Post::model()->getCurrentUsersPosts()->findAll();

foreach ($posts as $post)

{

// …

echo CHtml::activeHiddenField($post,’id_post’);

}



By clicking one record, it’s ID is send to server and it shows the detail of it. It works like this:




$post = Post::model()->findByPk($_POST[“id_user”]);

But what if somebody changed the hidden field? Than user will see detail of post that doesn’t belong to him and he will be able to change it.

Solution? … Simple.

Just add here the scope:




$post = Post::model()->getCurrentUsersPosts()->findByPk($_POST[“id_user”]);

Difference?

Edited post will be searched only among allowed records. If user changes the hidden field and the desired post is not his, he will receive error ($post will be empty) and you know exactly what he did.


It seems important but I don’t understand very well…

Forget what the poster of that piece of code said(i don’t want to be mean here).

Just use Yii::app()->user->getId() to be sure that you allow only the user who owns the posts to edit them.




//get user post list to edit:

Posts::model()->findAll( array(

     'condition'=>'user_id=:uid', 

     'params'=>array(':uid'=>Yii::app()->user->getId())

));


//get a single post for editing:

Posts::model()->find( array(

     'condition'=>'post_id=:pid AND user_id=:uid', 

     'params'=>array(':pid'=>$post_id, ':uid'=>Yii::app()->user->getId())

));



Sending PK’s along with the form, usually is a bad idea, but there are cases when you have no other way.

When this happens, you can do additional checks to see if the current entity can be changed by the current user, is not a big deal at all.

Ok, thanks twisted1919!