Manually Editing Data Models and Yii Components
Open model/User.php and find the rules() method. This function runs a validation on our user input, once again another impressive security feature of “sanitizing data” that Yii handles for us automatically. By default, you should see an line of code that reads :
array(‘username, password, salt, email’, ‘required’),
This tells the Yii framework to require these inputs before continuing. In no case – whether we were going to salt our tables or not – would we want to require any user input into the salt field. Further, we need to go into our database and make sure to either remove the salt field or set it being able to accept null values, otherwise we’ll get SQL errors when we try to create new user accounts. In my case, I just adjusted the salt column to accept null values. When I get ready to re-initiate the salting of my accounts before the production phase of this application, I can re-adjust my database rules.
So the above should be re-written like so:
array(‘username, password, email’, ‘required’),
Now, we won’t get any Yii validation errors when there is no user input from the salt field. This is just the beginning, however. There are several things we must do to store our user account data properly.
1. Ensure that the password field is putting the password into the database after it has hashed it
2. Ensure that our authentication logic hashes the password at login before checking the hashed password against what is in our database
3. Remove extraneous business logic in the Yii platform that is utilizing the salt field at time of authentication
A lot of the changes we still need to make are located in the components/UserIdentity.php and UserController.php files. The authentication system uses the methods and logic here to validate users. It is, by default, not set up. So, whether a Yii developer decides to utilize all security measures or scale them back a touch, the flexibility allows his/her preference and shouldn’t affect overall development time.
Let us begin with the User Controller file: The only thing that we must do here is ensure that the password is being md5 hashed before it is placed in the database. We need to locate the create action method. The way the controller works is that if the create form post variables are set, then it passes those variables to the model. Otherwise, it displays the create form view.
We have to re-write the code to look like so:
//this places an md5 hash on the password to obfuscate it
$_POST['User']['password'] = md5($_POST['User']['password']);
. . . . . .
All that is needed is to add the second line to the default create action. We pull the password out of the array, hash it, and put it back in the array. Simple as that.
Last, we must update the authentication logic in the User model and UserIdentity.php files. When a user tries to login, Yii will use the authenticate() method on the UserIdentity file. This method, in turn, calls the validatePassowrd() method on our User model file. By default, the validatePassword() method will use the hashPashword() method to check the salted record versus the salted input. We are disabling that, so we can ignore it.
The only function that is important to us is the validatePassword() method. We have to rewrite the logic to only check a single hashed password. I rewrote it like this:
public function validatePassword($password)
$password = md5($password);
if($password == $this->password)
This function hashes the user inputted password in the method itself, instead of calling the old hashPassword() function. It then checks the two. If they match, it returns true to the UserController.php file. Based off this, the authenticate() function should log in the user (or not), sets other session variables that are user dependant , and sets the login cookie, if enabled.
That’s it. We should have a simple Yii app that will allow us to create user accounts with one-way hashed passwords and validates our users based on that logic. Obviously, it would be easy to bring the salt field back into this process by using both the generateSalt() and hashPassword() methods already set up in the user model file in the user creation and validation processes, respectively.