Reputation: 21
when a user accesses an action where it is not permitted to access the _unauthorized method redirects incorrectly
correct: localhost / project / index
where he's redirecting: localhost / project / project / index
I am using acl
AppController.php
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array('Acl','Session','DebugKit.Toolbar','RequestHandler','Auth');
public $helpers = array('Html','Form','Session');
public $uses = array('Role');
public $roleId;
public $UAP;
public $aroId;
public function beforeFilter()
{
if ($this->Session->check('Config.language')) {
Configure::write('Config.language', $this->Session->read('Config.language'));
}
$this->Auth->authorize = array(
AuthComponent::ALL => array('actionPath' => 'controllers/','userModel' => 'Role'),
'Actions',
);
$this->Auth->authenticate = array(
'Blowfish' => array(
'userModel' => 'User'
)
);
if(!$this->_isAdmin()){
$this->roleId = $this->getRoleId();
$this->UAP = $this->Role->find('first',array('conditions'=>array('Role.id'=>$this->roleId)));
$aro = $this->Acl->Aro->find('first',array(
'conditions'=>array(
'Aro.model'=>'Role',
'Aro.foreign_key'=>$this->roleId)));
$this->aroId = $aro['Aro']['id'];
$allow = array_merge($this->_getAllowed(), array('display'));
$this->Auth->allowedActions = $allow;
}
//Configure AuthComponent
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->loginRedirect = array(
'controller' => 'pages',
'action' => 'display',
'home'
);
$this->Auth->authError = __('Not Authorized');
return parent::beforeFilter();
}
protected function _getAllowed($actionsIds = null, $controllerActions = null){
if(is_null($actionsIds)){
$actionsIds = $this->_getAllowedActionsIds();
}
if(is_null($controllerActions)){
$controllerActions = $this->_getControllerActions();
}
$allow = array();
foreach ($actionsIds as $value) {
array_push($allow, $controllerActions[$value]);
}
return $allow;
}
protected function _getAllowedActionsIds($allowedActions = null){
if(is_null($allowedActions)){
$allowedActions = $this->_getAllowedActions();
}
return array_values($allowedActions);
}
protected function _getAllowedActions($aroId = null, $acoId = null){
if(is_null($aroId)){
$aroId = $this->aroId;
}
if(is_null($acoId)){
$acoId = $this->_getControllerActionsIds();
}
$result = $this->Acl->Aco->Permission->find('list',array(
'conditions'=>array(
'Permission.aro_id'=>$aroId,
'Permission.aco_id'=>$acoId,
'Permission._create'=>1,
'Permission._read'=>1,
'Permission._update'=>1,
'Permission._delete'=>1,
),
'fields'=>array('id','aco_id'),
'recursive'=>'-1'));
return $result;
}
protected function _getControllerActionsIds($controllerActions = null){
if(is_null($controllerActions)){
$controllerActions = $this->_getControllerActions();
}
return array_keys($controllerActions);
}
protected function _getControllerActions($node = null){
if(is_null($node)){
$node = $this->_getNodeController();
}
return $this->Acl->Aco->find(
'list',array(
'conditions'=>array('Aco.parent_id'=>$node['0']['Aco']['id']),
'fields'=>array('Aco.id','Aco.alias'),
'recursive'=>'-1',
));
}
protected function _getNodeController(){
return $this->Acl->Aco->node("controllers/{$this->name}");
}
protected function _isAdmin(){
if($this->Auth->user() && $this->Auth->user('role_id') == 1){
$this->Auth->allow();
return true;
}
return false;
}
public function getRoleId(){
if(!is_null($this->Auth->user('role_id'))){
return $this->Auth->user('role_id');
}
return 9; //Usuário não cadastrado
}
}
?>
Upvotes: 2
Views: 2554
Reputation: 1
It seems that this behaviour occurs only if your project is located in a subdirectory.
The documentation states that "By default unauthorized user is redirected to the referrer URL or AuthComponent::$loginRedirect
or ‘/’
.", in this order.
If $loginRedirect
is an array, in AuthComponent::redirectUrl
the array is converted to an URL with a "special" parameter:
Router::url($redir + array('base' => false));
This parameter 'base' => false
strips off the base of the URL and therefore the redirect after login works even in subdirectories.
Unfortunately in AuthComponent's function _unauthorized
the URL from $loginRedirect
is converted from an array to a string by the use of Controller::referer
and the special parameter 'base' => false
is not used.
The solution could be to assure that the base is always stripped off and define $loginRedirect
in your AppController with the special parameter, e.g.
$this->Auth->loginRedirect = array(
'controller' => 'posts',
'action' => 'index',
'base' => false
);
If you decide to set $unauthorizedRedirect
, as suggested by Manoj Sharma, every unauthorized request is redirected to this URL and never to the referrer URL. This may be unwanted in case the user should just get the authError message after clicking an unauthorized link, but he should be redirected in case of typing an unauthorized URL.
Upvotes: 0
Reputation: 616
Ok, I found the answer for this. dude you can just add unauthorize redirect in AppController like this:
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'authError' => 'Did you really think you are allowed to see that?',
'unauthorizedRedirect' => array(
'controller' => 'users',
'action' => 'index',
'prefix' => false)
),
'Session'
);
Here you can specify any unauthorized redirection or custom unauthorized page
Upvotes: 2
Reputation: 97
Controls handling of unauthorized access.
* - For default value true
unauthorized user is redirected to the referrer URL
* or AuthComponent::$loginRedirect or '/'.
* - If set to a string or array the value is used as a URL to redirect to.
* - If set to false a ForbiddenException exception is thrown instead of redirecting.
So i approve what Charles Barry said
Upvotes: 1
Reputation: 21
I've been having this exact problem with Acl as well.
From what I can understand, when an authenticated user attempts to access an object which they are not authorised to do so, CakePHP first tries to redirect them to their referrer URL, or the $loginRedirect
, or then just plain root.
For some reason (which I don't pretend to understand) this is not working, and is outputting a garbled version of $loginRedirect
. In my case CakePHP was installed in localhost/cakephp
so I was getting a request for localhost/cakephp/cakephp
. If $loginRedirect
was pointing to a controller, it would direct to localhost/cakephp/cakephp/controller/method
.
A work-around is to go into AuthComponent.php (in the CakePHP library) and edit $unauthorizedRedirect
from
public $unauthorizedRedirect = true;
to
public $unauthorizedRedirect = '/';
Upvotes: 2