I have been playing around with cakePHP, trying to get the authentication to play nicely with bcrypt. bcrypt (blowfish crypt?) is a way of encrypting data which includes its own random salt in the hash. So you only need one field for the password but it is pretty secure.
After a lot of pain, it turns out that moving from the working basic ACL security (set up using the tutorial) to bcrypt is pretty easy. Two files to change! But it took me hours to work out because of silly errors like not having the password field in the database long enough for the hash (they appear to be 250 characters long).
I suspect I don’t need the ‘username’ => ‘username’ etc. but after a long effort to get it working I don’t really want to break it again.
<?php
/**
* Application level Controller
*
* This file is application-wide controller file. You can put all
* application-wide controller-related methods here.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Controller
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Controller', 'Controller');
/**
* Application Controller
*
* Add your application-wide methods in the class below, your controllers
* will inherit them.
*
* @package app.Controller
* @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
*/
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'authenticate' => array(
'Blowfish' => array(
'fields' => array(
'username' => 'username',
'password' => 'password'
),
'userModel' => 'User',
'scope' => array()
)
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
// Use bcrypt for hashes
Security::setHash('blowfish');
//Configure AuthComponent
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->loginRedirect = array(
'controller' => 'posts',
'action' => 'add'
);
$this->Auth->allow('display');
}
}
And change the beforeSave function in Model/User.php
// for acl with blowfish/bcrypt
public function beforeSave($options = array()) {
// hash the password
$this->data['User']['password'] = Security::hash($this->data['User']['password']);
return true;
}
Of course, enabling this breaks the working logins and you have to edit them to get the new hashes. You’ll be locked out if you don’t put $this->Auth->allow(); in the beforeFilter() function of the UsersController.php whilst you do it.