02 Mar 2012

Enable mod_status for CAKEPHP

I’ve been trying to isolate a CPU issue for an app running on Apache2 written with Cakephp. Apache has a module to monitor the server status with mod_status. http://www.debian-administration.org/article/Monitoring_Apache_with_mod_status

For Apache 1.2 enable mod_info and restart apache.

sudo a2enmod info
sudo /etc/init.d/apache2 restart

You should also enabled ExtendedStatus.

sudo vi /etc/apache2/conf.d/extendedstatus

Add the following

ExtendedStatus On

Once the module is enabled you have to enable the settings in the appropriate vhost in /etc/apache2/sites-enabled

<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from localhost ip6-localhost
</Location>

The problem if you are using cakephp is that the .htaccess will try to route the request which will fail. You have to edit your .htaccess file to look like the following:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !=/server-status
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
27 Jul 2011

Password Hashing in CakePHP

In a recent project I needed to add some validation to my User model. I’m using the Auth Component that is included with CakePHP. In this particular instance I wanted to allow a change password form. The form would have three fields (current_password, new_password, confirm_password). In the Model I wanted to first check if the current password was entered correctly.

Validation should always happen in the model so I created a new function that would check for the current password for the logged in user. The Auth component automatically hashes the password with SHA1 and uses the Security Salt as part of the password string to create the hash, so I needed to hash the “current_password” field from the form to check for a match. This is where I ran into the problem. I tried using the following:

function checkCurrentPassword($data) {
    $id = $this->data[$this->alias]['id']; // passed the user ID from the form as a hidden field
    $pwd = $this->field('password', array('id' => $id)); // get the current password from the database
    if(Security::hash($data['current_password']) != $pwd) {
        return false;
    }
    return true;
}

You can see that $id is passed from the form and $pwd is a variable for the current password in the database. Auth will automatically hash an input with the name “password”, but my form is using “current_password”, so it is sent in cleartext. This needs to be hashed first. I attempted to use the Security::hash function but my validated kept failing.

As it turns out the Security::hash function is only using SHA1 without the Security Salt added. What I was able to do is use the AuthComponent::password function instead which does use the Security Salt configured in core.php. New code looks like:

function checkCurrentPassword($data) {
    $id = $this->data[$this->alias]['id'];
    $pwd = $this->field('password', array('id' => $id));
    if(AuthComponent::password($data['current_password']) != $pwd) {
        return false;
    }
    return true;
}

The validate array would look like this:

var $validate = array(
'current_password' => array(
    'rule' => 'checkCurrentPassword',
    'message' => 'Current password was not entered correctly'
    )
);

Update: Security::hash actually takes a third parameter documented in the API to use the Security.salt value

Create a hash from string using given method. Fallback on next available method.

Parameters:

string $string required

String to hash
string $type optional NULL

Method to use (sha1/sha256/md5)
boolean $salt optional false

If true, automatically appends the application’s salt value to $string (Security.salt)

17 Jul 2011

Cakephp form input using select with options

There are times that you need to control the form->input helper with specific type setting and additional options. This is probably more comment when building custom form inputs that aren’t automagically being set from the model/controller.

I recently had to build a list on distinct dates, but prefer to user $this->Form->input, rather than $this->Form->select. I first built an indexed array containing my date fields.

array(
[xxxx-xx-xx] => xxxx-xx-xx
[yyyy-yy-yy] => yyyy-yy-yy
)

We’ll call this array $options. You can then build the input using something like

$this->form->input('Input Name', array(
  'type' => 'select',
  'options' => 'options',
  'label' => 'label',
  'empty' => 'No data selected'
);
30 Jun 2011

CakePHP 1.3 Virtual Fields

A new feature of CakePHP 1.3 is to create VirtualFields. Why do you care? Typically Cake can use the $displayField variable of a model for drop down lists in your views. Suppose a User model contains two columns, firstname and lastname. There is no way to concatenate this with the $displayField variable. You can however, use $virtualFields to create a new variable that can be assigned to $displayField.

My example uses an Employee model.

class Employee extends AppModel {
	var $name = 'Employee';
        var $virtualFields = array('full_name' => 'CONCAT(Employee.firstname, " ", Employee.lastname)');
        var $displayField = 'full_name';
}
15 Oct 2009

CakePHP Auth Component Problem

cakephp

I’ve been using CakePHP for my last few projects and recently ran into a problem that was driving me nuts. I have a few pages that don’t require any authentication. You can allow pages to be viewed by calling $this->Auth->allow(‘function_name’) in your beforeFilter() method. So, I set up my app_controller class with a before filter that looks something like this.

< ?php

class AppController extends Controller {

    var $helpers = array('Html', 'Form', 'Javascript');
    var $components = array('Auth');

    function beforeFilter() {
        $this->Auth->autoRedirect = false;
        $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
        $this->Auth->allow('display');
    }

}

?>

Read the rest of this entry »