redirect Access rules with Yii

后端 未结 4 575
暗喜
暗喜 2021-01-02 09:06

I am doing an app that requires authentication. In the index page of the app, I specified access rules like this

public function accessRules() {
    return a         


        
相关标签:
4条回答
  • 2021-01-02 09:20

    Since Yii v1.1.11 you can do the same thing with a callback and a closure, and just the default classes:

    array('deny',
    'actions'=>array('index','register','login','password'),
    'users'=>array('@'),
    'deniedCallback' => function() { Yii::app()->controller->redirect(array ('/home/index')); }
    ),
    
    0 讨论(0)
  • 2021-01-02 09:33

    this one worked for me since yii 1.1.11:

        array('deny',  // deny all users
                'users'=>array('*'),
                'deniedCallback' => $this->redirect('/')
            ),
    

    or use a static method in a Class:

    'deniedCallback' => array('ClassName', 'staticMethodName'),
    
    0 讨论(0)
  • 2021-01-02 09:41

    They 'll make you an offer you can't refuse

    Starting with Yii v1.1.11 CAccessRule defines the deniedCallback property that easily allows you to define a redirect when access is denied. I don't want to steal Iain Gray's thunder, so go upvote his answer (thanks to the commenter who alerted me to this as well).

    The original answer follows.

    Option 1: extend Yii to enable this functionality (correct)

    To do this we will need to write our own classes to be used instead of CAccessRule and CAccessControlFilter. For CAccessRule we just need to add one additional property:

    class MyAccessRule extends CAccessRule {
        public $redirect; // just add this property
    }
    

    For CAccessControlFilter we want to make it recognize the value of this property and act upon it. To do this, we need to override the preFilter method. Starting from the stock implementation, make a few changes:

    class MyAccessControlFilter extends CAccessControlFilter {
        protected function preFilter($filterChain)
        {
            $app=Yii::app();
            $request=$app->getRequest();
            $user=$app->getUser();
            $verb=$request->getRequestType();
            $ip=$request->getUserHostAddress();
    
            foreach($this->getRules() as $rule)
            {
                 if(($allow=$rule->isUserAllowed($user,
                                                 $filterChain->controller,
                                                 $filterChain->action,
                                                 $ip,
                                                 $verb))>0) // allowed
                     break;
                 else if($allow<0) // denied
                 {
                     // CODE CHANGED HERE
                     $request->redirect($app->createUrl($rule->redirect));
                     return false;
                 }
            }
    
            return true;
        }
    }
    

    Then we also need to override the setRules method, to instruct the filter to use the MyAccessRule class instead of the standard CAccessRule. Again, we modify the stock implementation by changing the line

    $r=new CAccessRule;
    

    to read

    $r=new MyAccessRule;
    

    After creating these classes, we have to also inject them into Yii's pipeline. To do this, override filterAccessControl on the base controller class; again, taking the stock implementation as reference and making a small change:

    public function filterAccessControl($filterChain)
    {
            $filter=new MyAccessControlFilter;  // CHANGED THIS
            $filter->setRules($this->accessRules());
            $filter->filter($filterChain);
    }
    

    That's it! You can now take advantage of the extra functionality in any controller by supplying the new redirect parameter to the access control filters like this:

    public function accessRules() {
        return array(
            array('deny',
                  'actions'=>array('index','register','login','password'),
                  'users'=>array('@'),
                  'redirect'=>array('home/index'),
            ),
        );
    }
    

    Option 2: implement access control inside each action (to be avoided)

    If you are not comfortable with subclassing Yii's core components, another option that I do not recommend is to embed both access control and redirection logic inside each controller action that you want to protect, or overriding the beforeAction method on your controllers to cover multiple actions from one location.

    0 讨论(0)
  • 2021-01-02 09:41

    $request->redirect($app->createUrl($rule->redirect));

    Should be:

    if(is_array($rule->redirect) && isset ($rule->redirect[0])){
        $request->redirect($app->createUrl($rule->redirect[0]));
    }
    
    0 讨论(0)
提交回复
热议问题