I am using CakePHP 2.3.6. I have several plugins in a project. I want to implement the login system in the UsersController. For that, I have this code in my AppController :
public $components=array('Session','Auth');
public function beforeFilter(){
if($this->Auth->user('role')=='admin'){
$this->Auth->loginRedirect(array('plugin'=>'admins_panel','controller'=>'admins','action'=>'index'));
$this->Auth->logoutRedirect(array('plugin'=>'admins_panel','controller'=>'admins','action'=>'index'));
}
}
So, it means, it'll redirect me to the Admin Panel plugin after I login. In my Users controller :
public $components=array('Auth');
public function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow();
}
public function login(){
if($this->request->is('post')){
if($this->Auth->login()){
$this->Session->setFlash('Welcome '.AuthComponent::user('name'));
$this->redirect($this->Auth->redirectUrl());
}else{
$this->Session->setFlash('Invalid username or password, please try again');
$this->set('title_for_layout','Error - Login');
}
}else
$this->set('title_for_layout','Login');
}
In the User model :
public $validate=array(
'email'=>array(
'rule'=>'isUnique',
'message'=>'This email address has already been taken. Use another one.'
),
'username'=>array(
'rule'=>'isUnique',
'message'=>'This username has already been taken.'
)
);
public function beforeSave($options=array()){
if(isset($this->data[$this->alias]['password']))
$this->data[$this->alias]['password']=AuthComponent::password($this->data[$this->alias]['password']);
return true;
}
My View file is :
<?php echo $this->Form->create('User');?>
echo $this->Form->input('username',array('type'=>'email'));?>
echo $this->Form->input('password',array('type'=>'password'));?>
echo $this->Form->submit('Login');
echo $this->Form->end();
?>
So, I thought it'd work, but its not working. When I try to login, it says "Invalid username or password, please try again.", as I set in the "login" function.
So, what should do here ? Please help me.
Thanks
Define authentication fields in your auth component:
public $Components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'username', 'password' => 'password'),
)
)
)
)
If you want to use the email for your authentication then use:
'fields' => array('username' => 'email', 'password' => 'password')
Related
I have created a little project with an admin section. I am using admin routes to redirect to admin actions in my controllers. The website has pages that are available to everyone with no login required. To access the /admin or /admin/users, etc... You must login.
I have spread my admin actions across my controllers like "admin_login", "admin_users", ...
So my question is, when someone goes to /admin/users or some other adminpage, I have to check in each controller action if the user is in the session and otherwise redirect to thelogin form.
Is there a way to do this in one place? I used a beforefilter in my AppController class.
When using something like this, I get an infinite loop:
AppController.php
class AppController extends Controller {
public $helpers = array('Paginator','Acl.AclHtml');
public $components = array('Acl', 'Session',
'Auth' => array(
'authError' => 'You are not authorized to access that location.',
'authorize' => array(
'Actions' => array(
'actionPath' => 'controllers')
),
'controllers' => array('users')
));
public function beforeFilter() {
if(isset($this->request->prefix) && ($this->request->prefix == 'admin')){
$username = $this->Session->read('Admin.username');
if (empty($username)) {
$this->redirect (array(
'controller'=>'users',
'action'=>'login',
'admin'=>true
));
} else {
$this->redirect (array(
'controller'=>'admin',
'action'=>'dashboard',
'admin'=>true
));
}
}
// LDAP
$server_ip = $_SERVER['SERVER_ADDR'];
$ldapIp = ClassRegistry::init('LdapIp');
$ldapIpCount = $ldapIp->find('count', array('conditions' => array('ldap_ip' => $server_ip)));
if ($ldapIpCount >= 1) {
$this->Auth->authenticate = array('Ldap');
} else {
$this->Auth->authenticate = array('Form');
}
$this->Auth->authenticate = array('Form');
$this->Auth->allow();
if (!$this->Auth->isAllow($this)) {
$this->set(array(
'message' => array(
'text' => __('un aunthaticated request'),
'type' => 'error',
'status' => "401"
),
'_serialize' => array('message')
));
throw new ForbiddenException();
}
}
}
The front login with LDAP (Active directory).
UsersController.php
App::uses('AppController', 'Controller');
App::uses('Sanitize', 'Utility');
class UsersController extends AppController {
public $components = array('Paginator', 'Session', 'RequestHandler', 'Auth', 'Acl');
public function admin_login() {
$this->layout = 'admin_login';
if ($this->request->is('post')) {
$username = $this->request->data['User']['username'];
$password = $this->request->data['User']['password'];
$password = Security::hash($password, null, true);
$logged_in = $this->User->find('count', array('conditions' => array('User.username' => $username, 'User.password' => $password, 'User.role' => 'Admin', 'User.active' => 1)));
if ($logged_in >= 1) {
$this->Session->setFlash(__('Login successful!'), 'default', array('class' => 'alert alert-success'));
$users = $this->User->find('first', array('conditions' => array('User.username' => $username, 'User.password' => $password, 'User.role' => 'Admin', 'User.active' => 1)));
$this->Session->write('Admin.id', $users['User']['id']);
$this->Session->write('Admin.username', $users['User']['username']);
$this->Session->write('Admin.group_id', $users['User']['group_id']);
$this->Session->write('Admin.full_name', $users['UserProfile']['fname'] . " " . $users['UserProfile']['lname']);
$this->redirect(array('controller' => 'admin', 'action' => 'dashboard', 'admin' => true));
} else {
$this->Session->setFlash(__('Username or password is incorrect!'), 'default', array('class' => 'alert alert-error'));
}
}
}
public function admin_logout() {
$this->Session->delete("Admin");
//$this->Session->destroy();
$this->Session->setFlash(__('Logged out successful!'), 'default', array('class' => 'alert alert-success'));
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => true));
}
}
Yoy are getting an infinite loop because beforeFilter() will be called when you attempt to access /admin/users/login.
The proper way of dealing with your needs is setting up the Auth Component.
Once you've set up component, in UsersController::beforeFilter() you have to allow access to those actions that don't require login by means of the allow() method. E.g.
public function beforeFilter() {
$this->Auth->allow(array('signup'));
parent::beforeFilter();
}
This is also applicable to any other controller with actions that need to be accessed by non logged in users.
The loginAction you define in the Auth component configuration will be automatically allowed access.
In the blog tutorial you will find a good example of the Auth component usage.
Edit
As mentioned, AppController::beforeFilter() is always called, even when you try to access /admin/users/login. To prevent this from happening, try adding the following condition:
if (empty($username) && $this->action!='login') {
$this->redirect (array(
'controller'=>'users',
'action'=>'login',
'admin'=>true
));
}
You wouldn't need this if you allowed AuthComponent to take care of authentication for you.
Still, there's no guarantee that your code will work as expected. You are making your life difficult by not using AuthComponent to its fullest. I recommend that you research on the topic:
Creating Custom Authorize objects in the Cookbook 2.x
LdapAuth in cakephp 2.0 in Stack Overflow
I'm trying to implement a login feature where a user can use his username or email address. I've worked out the login with both, but when the user logs in successfully with his email address, the authError still flashes (user is logged in). I've put a comment "HERE" down in the login action, and I'm not sure what happens after that with the redirect.
Here are the relevant bits of my code:
App Controoler:
public $components = array(
'Auth' => array(
'authorize' => 'controller',
'loginRedirect' => array(
'controller' => 'users',
'action' => 'welcome_page'
),
'loginError' => 'Invalid user name/password',
'authError' => 'You don\'t have permission'
),
'Session',
);
User Controller:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add');
}
public function login() {
// At this point, the Auth Component is unable to log in user, so check with email.
if (!empty($this->data) &&
!empty($this->Auth->data['User']['username']) &&
!empty($this->Auth->data['User']['password'])) {
// Look for user with email address using the entered username
$user = $this->User->find('first', array(
'conditions' => array(
'User.email' => $this->Auth->data['User']['username'],
'User.password' => $this->Auth->data['User']['password']
),
'recursive' => -1
));
// Check if a matching user is found and that if login was succesfull
if (!empty($user) && $this->Auth->login($user)) {
if ($this->Auth->autoRedirect) {
// NOTE: user trying to log in with email reaches HERE
$this->redirect($this->Auth->redirect()); // this is the default authentication redirect defined in App Controller
}
} else {
$this->Session->setFlash($this->Auth->loginError, $this->Auth->flashElement, array(), 'auth');
}
}
}
I edited your original post to delete the messages from the session variables.
<?php
$this->Session->delete('Message.flash');
$this->Session->delete('Message.auth');
?>
Hope this helps!
-Andrew
What I did
I used this part of the Cookbook to create my authentication: Link
After i was finished, i changed the fields to email and password (in AppController.php):
public function beforeFilter() {
$this->Auth->allow('index');
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
}
What happened
The login form always said that my password/email combination was not correct.
After a while searching and trying stuff, i added "$this->request->data" to the Auth->login() parameter in the login() function of the UsersController:
public function login(){
$this->layout = 'login';
if ($this->request->is('post')){
if ($this->Auth->login($this->request->data)){
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Ongeldig email adres of wachtwoord. Probeer het AUB opnieuw'));
}
}
}
This worked, but now i can't use "$user['id']" to get the loggedin users id. It says that it doesn't know the $user variable.
What I expected to happen
In the first place, it should have logged the user in without me adding the parameter. And second, it should have printed the loggedin user's id.
I hope someone can help me with the problem.
Thanks in advance!
fields is now in the authenticate array:
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email', ...)
)
)
see
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#configuring-authentication-handlers
either with
$this->Auth->authenticate = ...
or
public $components = array(
'Auth' => array(
'authenticate' => ...
)
);
but, as PHP freelancer stated, this is well documented.
what cookbook version did you use? the 2.x one?
I have 2 authenticate method for Auth component. Default and Special.
First method is for all users, and Special for my friends...
I want to change authenticate method to Special when posted role is equal to 2..
So I put this in my UsersController login method:
if($this->request->data['role'] == 2){
$this->Auth->authenticate = 'Special';
echo 'Method changed!';
}
if($this->Auth->login()){
......
}
and if AppController, where I set $components:
public $components = array('RequestHandler', 'Session',
'Auth' => array('authenticate' => 'Default'));
but, when I send a form with role=2, it prints Method changed but won't change the authenticate method and use Default method..
Have I made a mistake?
I've a simplier solution :
In your controller, define your new authenticate array :
$this->Auth->authenticate = array('Form' => array(
'userModel' => 'User',
'fields' => array('username' => 'login', 'password' => 'password'),
));
Then to make your changes effective in your application, simply write :
$this->Auth->constructAuthenticate();
That's all :)
I've had a similar problem and I solved it by defining the same variable in the beforeFilter action of the AppController:
function beforeFilter() {
parent::beforeFilter();
// Pass settings in
$this->Auth->authenticate = array('Form' => array(
'fields' => array('username' => 'email')
));
...
}
So in your case I would do the following in the AppController:
function beforeFilter() {
parent::beforeFilter();
if($this->request->data['role'] == 2){
$this->Auth->authenticate = 'Special';
echo 'Method changed!';
} else {
$this->Auth->authenticate = 'Default';
}
...
}
... and in the components declaration only write:
public $components = array('RequestHandler', 'Session', 'Auth');
I have tried most if not all tutorials for CakePHP 1.3 on their Auth method and non seem to work on CakePHP 2.0.
I can add users, hash the passwords, but the login feature does not work. It just refreshes the page when I click on login. No errors, no nothing.
I would appreciate some tips please and thank you for reading my question.
This my code
public function login()
{
if ($this->request->is('post') )
{
if( $this->Auth->login() )
{
// the redirect() function in the Auth class redirects us
// to the url we set up in the AppController.
return $this->redirect( $this->Auth->redirect());
}
else
{
$this->Session->setFlash(__('Email or password is incorrect',true));
}
}
}
Thanks,
Mahadeva Prasad
First of all check how you have hash the password.Also check the field length in database.
Preferred - varchar(255)
The password will be hash as follows.
class User extends AppModel {
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
return true;
}
}
Also as you are using FormAuthenticate try using this when declaring component.
public $components = array(
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login',
),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'username')
)
)
)
);
For more information refer http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html