简体   繁体   中英

Wrong Redirection CakePHP

Redirect AuthComponent::$unauthorizedRedirect

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
}
}
?>

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 = '/';

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

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

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, eg

$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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM