【问题标题】:redirect Access rules with Yii使用 Yii 重定向访问规则
【发布时间】:2012-03-21 12:37:54
【问题描述】:

我正在做一个需要身份验证的应用程序。在应用程序的索引页面中,我指定了这样的访问规则

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

在第一条规则中,操作“索引”、“注册”、“登录”和“密码”对经过身份验证的用户是不可访问的。但是,我不想显示此消息

Unauthorized
You are not authorized to perform this action.

You do not have the proper credential to access this page.

If you think this is a server error, please contact the webmaster. 

...当授权用户尝试访问这些操作时。相反,我想将它们重定向到另一个页面。如果我能在第一条规则中做这样的事情会很有用

array('redirect',
    'actions'=>array('index','register','login','password'),
    'users'=>array('@'),
    'url'=>array('home/index'),
    ),

【问题讨论】:

    标签: php yii


    【解决方案1】:

    从 Yii v1.1.11 开始,你可以用回调和闭包做同样的事情,只需要默认类:

    array('deny',
    'actions'=>array('index','register','login','password'),
    'users'=>array('@'),
    'deniedCallback' => function() { Yii::app()->controller->redirect(array ('/home/index')); }
    ),
    

    【讨论】:

    • 在接受的答案出现问题后(我敢肯定,由于我自己的错误),这对我来说是完美的。
    • 它是如何工作的?我的意思是,我可以在“允许”规则中使用它吗?你能给出它的描述吗?
    【解决方案2】:

    他们会给你一个你无法拒绝的提议

    从 Yii v1.1.11 开始,CAccessRule 定义了 deniedCallback 属性,它允许您在访问被拒绝时轻松定义重定向。我不想窃取Iain Gray's thunder,所以去投票他的答案(感谢commenter,他也提醒了我这一点)。

    原始答案如下。

    选项 1:扩展 Yii 以启用此功能(正确)

    为此,我们需要编写自己的类来代替CAccessRuleCAccessControlFilter。对于CAccessRule,我们只需要添加一个额外的属性:

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

    对于CAccessControlFilter,我们想让它识别这个属性的值并对其采取行动。为此,我们需要重写preFilter 方法。从stock implementation 开始,进行一些更改:

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

    那么我们还需要重写setRules方法,指示过滤器使用MyAccessRule类而不是标准的CAccessRule。同样,我们通过更改行来修改stock implementation

    $r=new CAccessRule;
    

    阅读

    $r=new MyAccessRule;
    

    创建这些类之后,我们还必须将它们注入到 Yii 的管道中。为此,请在基本控制器类上覆盖 filterAccessControl;再次以stock implementation 为参考并进行小改动:

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

    就是这样!您现在可以通过向访问控制过滤器提供新的redirect 参数来利用任何控制器中的额外功能,如下所示:

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

    选项 2:在每个动作内部实施访问控制(要避免)

    如果你不习惯继承 Yii 的核心组件,另一个我不推荐的选项是在你想要保护的每个控制器操作中嵌入访问控制和重定向逻辑,或者覆盖控制器上的beforeAction 方法,用于覆盖一个位置的多个操作。

    【讨论】:

    • 很好的答案!我正在寻找类似的东西,并会看到选项 1 的结果。
    • @WallyLawless:很高兴为您提供帮助;我还做了一个小修改,添加了一个如何使用这个新功能的示例。
    • 快速说明:如果您没有设置重定向规则,那么在失败时它将始终将您置于“webroot”。你可以通过检查来解决这个问题:if($rule-&gt;redirect) { /* do redirect */ } else { /* do default accessDenied */ }
    • 注意:在我重写的 CAccessControlFilterprivate 实现中,我无权访问私有属性 $_rules;为了解决这个问题,我将私有 $_rules 添加到 MyAccessControlFilter 并添加了 public function getRules() { return $this->_rules; }
    • 确保您在所有人下方阅读了 Iain Gray 的回答!它从 v1.1.11 开始工作,节省了我的时间和头痛。
    【解决方案3】:

    这个从 yii 1.1.11 开始为我工作:

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

    或在类中使用静态方法:

    'deniedCallback' => array('ClassName', 'staticMethodName'),
    

    【讨论】:

    • 如果你在回调的from中不写回调,每次都会执行。这是以声明的形式写的。
    • 这只是一个演示,每次都执行,因为上面的条件意味着“拒绝每个用户”
    【解决方案4】:

    $request-&gt;redirect($app-&gt;createUrl($rule-&gt;redirect));

    应该是:

    if(is_array($rule->redirect) && isset ($rule->redirect[0])){
        $request->redirect($app->createUrl($rule->redirect[0]));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多