I am trying to implement blowfish password hasher in my cakePHP app. I've followed along with the tutorial.
When trying to add a new user I'm getting a fatal error when I try to instantiate a new BlowfishPasswordHasher class in the beforeFilter function of my user model. The error states :Class 'BlowfishPasswordHasher' not found.
I saw the question here but it looks like I have everything setup correctly.
Here is relevant code in my app/Controller/appController:
class AppController extends Controller {
public $components = array(
'Flash',
'RequestHandler',
'Auth' => array(
'authenticate' => array(
'Form' =>array(
'passwordHasher' => 'Blowfish'
'fields' => array(
'username' => 'username',
'password' => 'password'
),
),
),
'loginRedirect' => '/trails',
'logoutRedirect' => '/',
),
);
app/Model/User.php
<?php
App::uses('AppModel', 'Model');
App::uses('BlowfishPasswordHasher', 'Conroller/Component/Auth');
class User extends AppModel {
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash($this->data[$this->alias]['password']
);
}
return true;
}
Any help is much appreciated!!!
Looks like you have a spelling mistake:
App::uses('BlowfishPasswordHasher', 'Conroller/Component/Auth');
Change this to:
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
There's no folder called Conroller and therefore, it's unable to locate the BlowFish library file.
Hope this helps.
Related
I'm having a very strange issue. I'm working with XAMPP on my local computer, and everything works perfect. But when I upload it to my server, suddenly ContainableBehavior stops recognizing associations.
Cake's version: 2.5.6
Here's XAMPP's phpinfo(): http://pastebin.com/DeZWMh42
And here's my server's phpinfo(): http://pastebin.com/rtZ0kTAM
Both locations have the exact same files and databases.
This is the error(s) I'm getting:
Warning (512): Model "Certificado" is not associated with model
"Usuario" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 342]
Warning (512): Model "Certificado" is not associated with model
"Alumno" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 342]
Warning (512): Model "Certificado" is not associated with model
"Usuario" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 342]
Warning (512): Model "Certificado" is not associated with model
"Alumno" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 342]
Basically, an Impresion belongs to an Usuario and to a Certificado, the latter also belongs to an Usuario (may be a different one) and to an Alumno. Obviously I cut out all the irrelevant parts (let me know if you need more.)
This is where I'm using ContainableBehavior (Impresion's Controller):
(I'm getting the error on /impresions/index)
class ImpresionsController extends AppController {
public $components = array('Paginator');
public $uses = array('Usuario', 'Alumno', 'Certificado', 'Impresion');
public function index(){
$this->paginate = array(
'limit' => 10,
'order' => array('fecha_creacion' => 'desc'),
'contain'=>array(
'Usuario',
'Certificado' => array(
'Usuario',
'Alumno'
)
),
);
$results = $this->paginate('Impresion');
$this->set('impresiones',$results);
}
}
And in the view I just use a foreach($impresiones).
Impresion's Model:
class Impresion extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'Certificado' => array(
'className' => 'certificado',
'foreignKey' => 'certificado_id',
),
'Usuario' => array(
'className' => 'Usuario',
'foreignKey' => 'usuario_id',
'fields' => array('nombre','codigo')
),
);
}
Usuario's Model:
class Usuario extends AppModel {
public $hasMany = array('Certificado','Impresion');
public $actsAs = array('Containable');
}
Certificado's Model:
class Certificado extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'Usuario' => array(
'className' => 'Usuario',
'foreignKey' => 'usuario_id',
),
'Alumno' => array(
'className' => 'Alumno',
'foreignKey' => 'alumno_id',
)
);
public $hasMany = 'Impresion';
}
Alumno's Model:
class Alumno extends AppModel {
public $actsAs = array('Containable');
public $hasMany = 'Certificado';
}
Local query: http://pastebin.com/B5MRp3FS
Server's query: http://pastebin.com/J2H4U6Ge
I'm completely lost here. Why does it work perfectly fine on my computer, but breaks on the server? Everything else works, it's just ContainableBehavior that's having problems.
I can't believe it.
Disregard everything.
This:
'className' => 'certificado',
Should've been this:
'className' => 'Certificado',
Sorry for wasting your time, I'm an idiot
I guess this is a silly question but I'm having trouble logging in to the restricted sections of a site I'm building in Cake.
For starting I see that the password string in $this->request->data['Usuario']['clave'] is not the same as the hashed string using SimplePasswordHasher in the beforeSave function at the model. I should also say that the model is not the default Users model, because I'm writing the application for spanish language and I didn't want to use the default model, so my configuration of the component is:
class AppController extends Controller {
/*function beforeFilter() {
date_default_timezone_set('America/Mexico_City');
}*/
public $components = array(
'Session',
'Auth' => array(
'Form'=>array(
'userModel' => 'Usuario',
'unauthorizedRedirect' => false,
'loginRedirect' => array(
'controller' => 'ComplejosResidenciales',
'action' => 'index'
),
'logOutRedirect' => array(
'controller' => 'Usuarios',
'action' => 'index'
),
'fields' => array(
'username' => 'usuario',
'password' => 'clave'
),
'authorize' => 'Controller'
)
)
);
}
So I decided not to hash the password field, but still to no avail.
I wish anyone could lend me a hand on this because I'm newbie to CakePHP and don't know how to fix it.
I figure it must be something with the Auth->login() method because I'm not following conventions here, but I don't know how to configure the said method. Currently is like follows:
public function login() {
if($this->request->is('post')) {
if($this->Auth->login()) {
return $this->Auth->redirectUrl($this->Auth->redirectUrl());
}
else {
$this->Session->setFlash(__('Las credenciales proporcionadas no son correctas'), 'default', array(), 'auth');
}
As rrd pointed, my $components array was wrong, so I changed it to:
public $components = array(
'Session',
'Auth'=>array('loginRedirect'=>array('controller'=>'ComplejosResidenciales', 'action'=>'index'), 'logOutRedirect'=>array('controller'=>'Usuarios', 'action'=>'index'), 'loginAction'=>array('controller'=>'Usuarios', 'action'=>'login'), 'authenticate'=>array('Form'=>array('userModel'=>'Usuario', 'fields'=>array('username'=>'usuario', 'password'=>'clave')))));
Which is better, according to cakephp.org
Do not put other Auth configuration keys (like authError, loginAction etc) within the authenticate or Form element. They should be at the same level as the authenticate key.
But it isn't working.
Been struggling with it and I can't get the hang of it, I wish someone would point out what I'm doing wrong. In my AppController I have declared the component and the beforeFilter function like this:
public $components = array('Auth'=>array('loginRedirect'=>array('controller'=>'ComplejosResidenciales', 'action'=>'index'),
'logoutRedirect'=>array('controller'=>'Usuarios', 'action'=>'login'),
), 'Session');
public function beforeFilter(){
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'Usuario', "fields" => array("username" => "usuario", "password" => "clave"), 'Form'));
}
And then I have the login function which goes (obviously I guess) in the UsuariosController, like this:
public function login() {
if($this->request->is('post')) {
if($this->Auth->login()) {
return $this->Auth->redirectUrl($this->Auth->loginRedirect);
}
else {
$this->Session->setFlash(__('Las credenciales proporcionadas no son correctas'), 'default', array(), 'auth');
}
}
}
But I just keep seeing the message "Las credenciales proporcionadas no son correctas". I don't know if I'm calling the method of Auth component correctly in the part $this->Auth->login() because apparently I have no result when calling it like that, without arguments, but I tried calling it with the argument $this->request->data and as a result it didn't mattered what I wrote in the username and password fields, anything would pass, which is bad, of course.
Now I see why coding $this->Auth->login($this->request->data) resulted in giving unrestricted access:
In 2.x $this->Auth->login($this->request->data) will log the user in with whatever data is posted, whereas in 1.3 $this->Auth->login($this->data) would try to identify the user first and only log in when successful.
According to cake's manual. I can't seem to read correctly any document about this. Anyway, I beg someone would help me because I'm in a hurry here. After reading some other documents I guess that Auth component should handle everything correctly, as long as I provide the right configuration, so I've ended up doing a beforeFilter() call in the AppController, like this:
var $components = array('Auth', 'Session');
public function beforeFilter() {
$this->Auth->loginAction = array('controller'=>'Usuarios', 'action'=>'login');
$this->Auth->redirectLogin = array('controller'=>'ComplejosResidenciales', 'action'=>'add');
$this->Auth->authenticate = array('Form'=>array('userModel'=>'Usuario', 'fields'=>array('username'=>'usuario', 'password'=>'clave')));
}
Then, in my "UsuariosController" I do:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index', 'view', 'add', 'edit', 'delete');
}
And I have my login and logout functions, very simple, but it's not working, and it does not redirect me upon logging in nor does it let me access any other controller, it seems to do nothing. Please help!
/**
* login and logout functions
*
*/
public function login() {
}
public function logout() {
$this->redirect($this->Auth->logout());
}
You should change more things.
$components should be something like this:
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username'=>'usuario', 'password'=>'clave')
)
)
)
);
I am not sure about userModel, check the manual.
Than you should implement isAuthorized
function isAuthorized($user){
if(in_array($this->action, array('view', 'edit')))
return true;
return false;
}
beforeFilter is not necessary for your case.
Your login method is something like this.
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}
else {
$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
}
}
}
Again, I recommend you to read the manual or the book mentioned above. It has a free sample, I think You will get the main idea by that.
How to override Yii Login URL Modul for module?
here is the main configuration for base application:
return array(
.........
// application components
'components'=>array(
'user'=>array(
// enable cookie-based authentication
'allowAutoLogin'=>true,
'loginUrl' => '/site/login',
),
..........
);
And then i have agent module, i want in this this module the login URL is different and login method is also different.
class AgentModule extends CWebModule {
public function init() {
// this method is called when the module is being created
// you may place code here to customize the module or the application
// import the module-level models and components
$this->setImport(array(
'agent.models.*',
'agent.components.*',
));
$this->defaultController = 'default';
$this->layoutPath = Yii::getPathOfAlias('agent.views.layout');
$this->components = array(
'user' => array(
'class' => 'AgentUserIdentity',
'loginUrl' => '/agent/default/login',
)
);
}
.......
But i don't know why this not work.
Please help... (T.T)
Use this code
class AgentModule extends CWebModule {
public $assetsUrl;
public $defaultController = 'Login';
public function init() {
// this method is called when the module is being created
$this->setComponents(array(
'errorHandler' => array(
'errorAction' => 'admin/login/error'),
'user' => array(
'class' => 'CWebUser',
'loginUrl' => Yii::app()->createUrl('admin/login'),
)
)
);
Yii::app()->user->setStateKeyPrefix('_admin');
// import the module-level models and components
$this->setImport(array(
'admin.models.*',
'admin.components.*',
)
);
}
public function beforeControllerAction($controller, $action) {
if(parent::beforeControllerAction($controller, $action)) {
// this method is called before any module controller
//action is performed
$route = $controller->id . '/' . $action->id;
$publicPages = array(
'login/login',
'login/error',
);
if (Yii::app()->user->name !== 'admin' && !in_array($route,
$publicPages)) {
Yii::app()->getModule('admin')->user->loginRequired();
} else {
return true;
}
}
else
return false;
}
}
In 2nd code block in your question you defined user component for module AgentModule.
If i understand right, somewhere in your view or controller you use Yii::app()->user->loginUrl, right? To get url defined in AgentModule you should use Yii::app()->user->controller->module->user but only while in AgentModule context.
Easiest way to make it different is to define somewhere login urls for module, and for app, and just use this predefined urls.
Try reading about module compoents here: http://www.yiiframework.com/wiki/27/how-to-access-a-component-of-a-module-from-within-the-module-itself/
class WebUser extends CWebUser {
public $module = array();
public function init() {
parent::init();
if(isset($this->module['loginUrl'])){
if(!isset($this->module['moduleId'])){
throw new Exception('moduleId Must defined');
}else{
$moduleId = Yii::app()->controller->module->id;
if($moduleId == $this->module['moduleId']){
#$this->loginUrl = Yii::app()->request->redirect(Yii::app()->createUrl($this->module['loginUrl']));
$this->loginUrl = array($this->module['loginUrl']);
}
}
}
}
}
after that you need to do some changes under config file i.e
return array(
'components' => array(
'user' => array(
'allowAutoLogin' => true,
'class' => 'WebUser',
'module' => array(
'loginUrl' => '/r_admin',
'moduleId' => 'r_admin'
)
),
)
);
I'm using CakePHP 2.2.4, and I have started to work with Atuh Componenet.
This is my AppController:
class AppController extends Controller {
public $components = array('Auth', 'Session');
public function beforeFilter() {
$this->Auth->authorize = array('Controller');
$this->Auth->authenticate = array(
'Form' => array (
'scope' => array('User.active' => 1),
'fields' => array('username' => 'email', 'password' => 'password'),
)
);
}
public function isAuthorized($user) {
debug($user);
return true;
}
}
This is my User.php model
class User extends AppModel {
public $name = 'User';
/* Relazioni */
public $hasOne = 'Profile';
public $belongsTo = 'Role';
public $hasMany = array(
'Lead' => array(
'className' => 'Lead'
)
);
}
and this is my UserController.php
<?php
App::uses('AppController', 'Controller');
class UsersController extends AppController
{
public $name = 'Users';
public $uses = array();
public function beforeFilter()
{
parent::beforeFilter();
}
public function login()
{
if ($this->request->is('post'))
{
if ($this->Auth->login())
{
debug('Logged');
}
else
{
$this->Session->setFlash('Login non autorizzato', 'default', array('class' => 'errore'), 'login');
}
}
}
public function logout()
{
$this->redirect($this->Auth->logout());
}
}
I have a strange problem using Auth Component, because at the end of the layout I have sql_dump element, that prints NO QUERY.
However, If i put correct values I do not login
Why does Auth component is not working ?
EDIT:
The data of the request is:
Array
(
[User] => Array
(
[email] => test#test.it
[pwd] => abc
)
)
Your code in AppController is wrong
public function beforeFilter() {
$this->Auth->authorize = array('Controller');
$this->Auth->authenticate = array(
'Form' => array (
'scope' => array('User.active' => 1),
// password != pwd as you post it
'fields' => array('username' => 'email', 'password' => 'password'),
)
);
}
Change it to
'fields' => array('username' => 'email', 'password' => 'pwd'),
or make sure to post password instead of pwd in your form
Please see https://github.com/cakephp/cakephp/blob/master/lib/Cake/Controller/Component/Auth/FormAuthenticate.php for documentation on the matter
I'd like to post-fix this answer for anyone arriving here, who is unable to get logged in using Auth for which this example does not DIRECTLY Apply.
An important thing to remember is that Auth is expecting the underlying database columns to be "username" and "password". If for whatever reason you defer from this, for example if you want to validate on a users email (very common) and you change the table's column name to reflect this, than you must tell Auth about this.
The reason is because the underlying query will fail. Ultimately all that's happening behind the scene is a simply query matching the specified fields. For example (not exact - simply for demonstration purposes -- select *'s are bad):
SELECT * FROM users WHERE username = 'blahblahblah' AND password = 'someInsan31yh4sh3dpassw0rd'
If your underlying table is missing a "username" column in loo of an "email" column, than this query will obviously fail. Resulting in the inability to login and usually with no indication that the query failed (it is even omitted from the SQL dump). The following code in your AppController however will solve you issues:
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'columnUsedForValidatingUsername', 'password' => 'columnUserForValidatingPassword')
)
)
)
);
Jippi's answer was completely correct in this case. But I feel as though as an answerER on StackOverflow you owe it to anyone finding this to explain WHY the problem is occurring and provide an unspecific answer.
Cheers
i try to program a LdapAuthentication and i need some help.
First i need to configure the "$components" in /app/Controller/
Component/AppController.php
<?php
class AppController extends Controller {
var $components = array('Auth' => array(
'Ldap',
'authError' => 'Not allowed here',
'authenticate' => array('Form' => array(
'fields' => array(
'username' => 'username',
'password' => 'password',
'domain' => 'domain'
)
)
),
'authorize' => true,
), 'Session');
}
?>
Then i create a LdapAuthorize.php like
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#creating-custom-authorize-objects
<?php
App::uses('BaseAuthorize', 'Controller/Component/Auth');
class LdapAuthorize extends BaseAuthorize {
public function authorize($user, CakeRequest $request) {
echo "test";
}
}
?>
But when i try to login with
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Username or password is incorrect'),
'default', array(), 'auth');
}
cakephp doesn't use my authorize function.
What i do wrong? Please help.
Here is a working Ldap Auth class for 2.0.x
https://github.com/analogrithems/idbroker/tree/dev_cake2.0
with a blog post detailing it here:
http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/
** ALSO **
Your Auth configuration is wrong - the authorize key takes a string or array - a boolean true isn't going to do anything.
If you want it to check an isAuthorized action in the controller - set it like so:
<?php
...
public $components = array( 'Auth' => array(
...
'authorize' => array( 'Controller' ),
...
));
?>
You are passing a boolean parameter here, and have no isAuthorized function in your AppController. Also, you are using old php4 syntax to declare your member variables (use public, protected or private instead of "var")