I just started trying to learn cakephp auth, i just copied and pasted the code, trying to understand it. I can't figure out what is directly the redirect
//app controller
//is empty i know in some cases you put it here, i'm just tested it in the user controller
//user controller
public $components = array('Paginator',
'Session',
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login',
'plugin' => 'users'
),
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
)
)
);
public function beforeFilter() {
$this->Auth->allow('index', 'view');
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
// Prior to 2.3 use
// `return $this->redirect($this->Auth->redirect());`
} else {
$this->Session->setFlash(
__('Username or password is incorrect'),
'default',
array(),
'auth'
);
}
}
}
I understand the before filter makes sense, it only allows index and view, i have another controller called admin which redirects to the login page if your not logged in
but for somme reason it keeps redirecting to users/users/login, i want it to go to users/login? How do i fix this?
you just have to put the controller wherever you go and the action
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect(array('controller' => 'users', 'action' => 'login'));
}
} else {
$this->Session->setFlash(__('Invalido nombre de usuario o contraseƱa'));
}
}
Related
I added a prefix admin and changed the controller from Userscontroller to LoginController now the localhost:8765/admin works fine but localhost:8765/admin/login/check_login sbut when i submit my form it give me a error Error: The requested address '/admin/login/check-login' was not found on this server where check_login is my auth action
Router
Router::prefix('admin', function ($routes) {
$routes->connect('/', ['controller' => 'Login', 'action' => 'display','login']);
});
App Controller
public function initialize() {
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
]
],
'loginAction' => [
'controller' => 'Login',
'action' => 'check_login',
'prefix' => 'admin'
],
]);
// Allow the display action so our pages controller
// continues to work.
$this->Auth->allow(['display']);
Check Login Action
public function check_login() {
if ($this->request->is('post')) {
$admin = $this->Auth->identify();
if ($admin) {
$this->Auth->setUser($admin);
$result['status'] = 'success';
echo json_encode($result);
}
$result['status'] = 'failure';
$result['message'] = 'Your username or password is incorrect';
echo json_encode($result);
die;
}
}
Thanks in advance
Why are you complicating? The easiest way:
Create Admin folder in you Controller app folder.
Inside - create UsersController.php and make login method. All functions inside Admin folder will be using only with Admin prefix in URL.
Next - You can map the URL /admin/login to your login() action of users controller using following route:
Router::prefix('admin', function ($routes) {
// Because you are in the admin scope,
// you do not need to include the /admin prefix
// or the admin route element.
$routes->connect('/login', ['controller' => 'Users', 'action' => 'login']);
});
This is the easiest way.
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.
When i follow $this->Auth->allow('login'); this approach, we are not able to redirect to dashboard page. If i follow $this->Auth->allow(); this approach we are able to redirect to dashboard page.
But i need to use first approach for login.
I have a AppController.php which is performed Login Action.
Below is the AppController.php Code
function beforeFilter() {
Security::setHash('md5');
// Authenticate
$this->Auth->authorize = 'Controller';
$this->Auth->autoRedirect = false;
$subdomain = substr( env("HTTP_HOST"), 0, strpos(env("HTTP_HOST"), ".") );
if($this->params['controller']=="moderator")
{
//$this->Auth->allow(); // if i use this one my code is working fine.
$this->Auth->allow('login');
$this->Auth->loginAction = array('controller' => 'moderator', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'moderator', 'action' => 'dashboard');
$this->Auth->loginError = 'No username and password was found with that combination.';
$this->Auth->logoutRedirect = array('controller' => 'moderator', 'action' => 'login');
AuthComponent::$sessionKey = 'Auth.Admin';
}
}
when we are login the page it will goto ModeratorController.php controller page and then check the usename and password using Auth , if username & password correct it will call the dashboard function.
Below is the ModeratorController.php Code
class ModeratorController extends AppController {
public $components = array('RequestHandler','Session',
'Auth'=>array(
'authenticate' => array(
'Form' => array(
'fields'=>array(
'username'=>'username',
'password'=>'password'
),
'userModel'=> 'Admin'
),
),
'loginAction' =>array(
'Controller' => 'moderator',
'action' => 'login'
),
'loginRedirect'=>array('Controller'=>'moderator', 'action'=>'index'),
'logoutRedirect'=>array('Controller'=>'moderator', 'action'=>'index'),
'authError'=>"You can't access that page",
'authorize'=>'Controller',
'loginError'=> 'Login error',
)
);
public $helpers = array('Js' => array('Jquery'),'Html','Paginator');
function beforeFilter() {
//used version cake 2.3.0.
parent::beforeFilter();
}
// for moderator login process
public function login() {
if($this->Session->read('Auth.Admin.admin_id'))
{
$this->redirect('dashboard');
}
if($this->request->data)
{
$this->Admin->set($this->data);
if($this->Admin->validates())
{
if($this->Auth->login()){
//$this->redirect('/moderator/dashboard'); // result: redirect to moderator/login
//$this->redirect(array('controller' => 'moderator', 'action' => 'dashboard')); // result: redirect to moderator/login
//$this->redirect($this->Auth->redirect()); // result: redirect to moderator/login
//$this->redirect(array('action' => 'dashboard')) // result: redirect to moderator/login
//$this->redirect('dashboard12'); // result: redirect to moderator/dashboard12 and give me 404. That result is correct
//$this->redirect('/dashboard'); // result: redirect to /dashboard and give me 404. That result is also correct
$this->redirect('dashboard')) // result: redirect to moderator/login
}
else
{
$this->Session->setFlash(__('Invalid email or password, try again'));
}
}
}
}
public function dashboard()
{
echo "I am in dashboard";
exit();
}
}
Thanks
I see a few things that are technically wrong:
When building in CakePHP you should follow its standards
You should have moderators as your controller and not moderator
You make reference to dashboard.php
Is that a controller? or are you referring to the method
If you have a controller name ModeratorsController.php and a method there name dashboard(), then you can redirect like this:
$this->redirect(array('controller' => 'moderators', 'action' => 'dashboard'));
or you could even redirect like this
$this->redirect('/moderators/dashboard');
If the dashboard.php file you make reference is actually the controller, which in this case should be DashboardsControler.php, then you have to redirect to
$this->redirect('controller' => 'dashboards');
or
$this->redirect('/dashboards');
$this->redirect('dashboard');
Should be
$this->redirect(array('action' => 'dashboard'));
if this action is also in the dashboards controller.
Never use strings for links and redirects to internal pages of your app, only external links should use the string notation.
Also, is there any specific reason why you're not using the CookieComponent? Your cookie content won't be encrypted at all and you set a ton of cookies. Use the component.
Ok this is the scenario:
Admin logs in
Admin logs out
Normal user logs in
Redirected to admin page!
If I delete cookies stored however before logging in as a normal user, login works as expected. Another strange thing I have noticed is that the admin redirect in my login function is not actually ran when the normal user logs so they are being redirected elsewhere.
Here is some code:
Users Controller:
<?php
public function login() {
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->Auth->login()) {
//if login successful update logged in User as login does not use recursive find
$this->User->id = $this->Auth->user('id');
$this->User->read();
$this->Auth->login($this->User->data);
if($this->Login->isRole($this->Auth->user(), 'Admin')) {
//redirect admins to admin page, not ran when error occurs!!
$this->redirect(array('controller' => 'users', 'action' => 'index', 'admin' => true));
} else {
//isAuthorised in AppController takes care of redirect to registration page if required
$this->redirect($this->Auth->redirect());
}
} else {
//if login unsuccessful
$this->Session->setFlash(
__('Invalid username or password, please try again.'),
'alert',
array(
'plugin' => 'TwitterBootstrap',
'class' => 'alert-error'
)
);
}
}
//set layout
$this->layout = 'not_logged_in';
//set title
$this->set('title_for_layout', 'Login');
}
public function logout() {
//logout
$this->redirect($this->Auth->logout());
}
public function isAuthorized($user) {
if(parent::isAuthorized($user)) {
//call parent method for redirect and admin permission
return true;
}
switch ($this->action) {
case 'add':
case 'resetPassword':
case 'login':
//logged in users cannot access registration, login or password reset pages
return false;
break;
case 'add_role':
//check user is finshing registration or has a role request accepted
return (!$this->Login->isRegistrationComplete($user) || $this->Login->isRoleRequestAccepted($user));
break;
default:
//all loogged in users can access the rest of User controller
return true;
break;
}
}
php?>
App Controller:
<?php
public $components = array(
'Session',
'Auth' => array(
'className' => 'UserAuth',
'loginRedirect' => array('controller' => 'users', 'action' => 'view'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authorize' => array('Controller'),
'authenticate' => array('Blowfish'),
'authError' => 'Please login.',
'loginError' => 'Invalid Username or Password entered, please try again.',
),
'Login'
);
public function isAuthorized($user) {
//set values needed for all logged in pages
$this->set('loggedIn', $user);
$this->set('role', $user['User']['role']);
if($this->Login->isAccessing($this, 'users', 'logout')) {
//never prevent user from logging out
return true;
}
if($this->Login->isRole($user, 'Admin')) {
//admin can access every action
return true;
} elseif ($this->request->prefix === 'admin') {
//only admins allowed on admin pages
throw new Exception('You do not have permission to access this page.', 1);
}
//get user role and requested role
$roles = $this->Login->getRolesCurrentAndNew($user);
if($this->Login->isRoleRequestAccepted($user)) {
//user has an accepted role request
$controller = 'users';
$action = 'add_role';
if($this->Login->isRedirectRequired($this, $controller, $action)) {
//if user is already accessing registration this check prevents redirect loops
if ($this->Login->isRegistrationComplete($user)) {
//display flash based on registration status
$this->Session->setFlash(
__('Your request for the role of '. strtolower($roles['new']) . ' has been accepted, please enter additional details.'),
'alert',
array(
'plugin' => 'TwitterBootstrap',
'class' => 'alert-success'
)
);
} else {
$this->Session->setFlash(
__('Please complete your registration.'),
'alert',
array(
'plugin' => 'TwitterBootstrap',
'class' => 'alert-success'
)
);
}
$this->redirect(array('controller' => $controller, 'action' => $action));
}
} elseif (!$this->Login->isRegistrationComplete($user)) {
//user has not registered yet and role request is not accepted
if(!$this->Login->isRegistrationComplete($user)) {
//user has not completed registration yet, awaiting approval
throw new Exception('Your registration request is awaiting approval from a member of the admin team.', 1);
}
}
return false;
}
?>
Routes config:
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/register', array('controller' => 'users', 'action' => 'add'));
Router::connect('/register/role', array('controller' => 'users', 'action' => 'add_role'));
Router::connect('/', array('controller' => 'users', 'action' => 'view'));
Router::connect('/admin', array('controller' => 'users', 'action' => 'index', 'admin' => true));
Router::connect('/users/manageRoleRequest', array('controller' => 'roleRequests', 'action' => 'add'));
I eventually realised that CakePHP automatically takes you to the last page you were viewing when you log out and in on the same machine, regardless of whether or not you're logging in as a different user or not.
From the docs:
property AuthComponent::$logoutRedirect
The default action to
redirect to after the user is logged out. While AuthComponent does
not handle post-logout redirection, a redirect URL will be returned
from AuthComponent::logout().
Defaults to AuthComponent::$loginAction.
Meaning:
$this->Auth->logout()
will return a string url. Nothing more.
You wrap it with a redirect to redirect to this url:
public function logout() {
$this->redirect($this->Auth->logout());
}
So, no, Cake will only redirect you to the specific action you specified via "loginRedirect" setting.
In your case your login view.
I tried the following and it seemed to work for me
public function logout() {
$logout_redirect = $this->Auth->logout();
$this->Auth->redirectUrl($this->Auth->redirect());
return $this->redirect($logout_redirect);
}
Just starting to learn the CakePHP framework. I'm using the Auth component, and all my actions that require a user to be logged in redirect to users/login rather than login/login (my non-standard controller). Anyone know where I can change this setting? Also, how does the auth component work across multiple controllers? Will I have to redefine this auto-redirect in every controller?
<?php
class LoginController extends AppController {
public $name = 'Login';
public $components = array('Auth');
public $helpers = array('Html', 'Form' );
function beforeFilter() {
// tell Auth not to check authentication when doing the 'register' action
$this->Auth->allow('register');
$this->Auth->userModel = 'Login';
}
function register() {
if (!empty($this->data)){
if ($this->Login->save($this->params['data'])) {
$this->flash('Your registration information was accepted. Welcome!');
$this->Auth->login($this->data);
$this->redirect(array('action' => 'index'));
} else {
$this->flash('There was a problem with your registration', '/login/knownusers');
}
}
}
function createprofile() {
}
function knownusers() {
$this->set('knownusers', $this->Login->find(
'all',
array(
'fields' => array('id','username', 'password', 'fk_profile_id'),
$this->redirect(array('action' => 'index'));
} else {
$this->flash('There was a problem with your registration', '/login/knownusers');
}
}
}
function createprofile() {
}
function knownusers() {
$this->set('knownusers', $this->Login->find(
'all',
array(
'fields' => array('id','username', 'password', 'fk_profile_id'),
'order' => 'id DESC'
)
));
}
function login() {
}
function logout() {
$this->redirect($this->Auth->logout('login/login'));
}
}
?>
If your entire website needs to be protected, then you can define the Auth component in your AppController which will cause those rules to apply to every controller that inherits from that object (i.e. all controllers on your site).
The CakePHP Authentication Documentation outlines all the parameters you need in order to accomplish what you are trying to do. You should be able to define the login redirect when you setup the Auth component:
public $components = array(
'Auth' => array(
'loginAction' => array('controller' => 'User', 'action' => 'login')
)
);
You can put this statement in your beforeFilter()
$this->Auth->loginAction = array('admin' => false, 'controller' => 'login', 'action' => 'login');
Also you do not need to define this in every controller. If there is any logic you need to execute for every controller, I would put it in beforeFilter() of AppController...