使用Yii重定向访问规则

Hil*_*lmi 9 php yii

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

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

在第一条规则中,操作'index','register','login'和'password'对于经过身份验证的用户是不可访问的.但是,我不想显示此消息

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. 
Run Code Online (Sandbox Code Playgroud)

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

array('redirect',
    'actions'=>array('index','register','login','password'),
    'users'=>array('@'),
    'url'=>array('home/index'),
    ),
Run Code Online (Sandbox Code Playgroud)

小智 28

从Yii v1.1.11开始,您可以使用回调和闭包执行相同的操作,并且只使用默认类:

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


Jon*_*Jon 23

他们会给你一个你不能拒绝的报价

从Yii v1.1.11开始,CAccessRule定义了deniedCallback允许您在拒绝访问时定义重定向的属性.我不想偷Iain Gray的雷声,所以请回答他的回答(感谢评论者提醒我这一点).

原来的答案如下.

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

为此,我们需要编写自己的类来代替CAccessRule和使用CAccessControlFilter.因为CAccessRule我们只需要添加一个额外的属性:

class MyAccessRule extends CAccessRule {
    public $redirect; // just add this property
}
Run Code Online (Sandbox Code Playgroud)

因为CAccessControlFilter我们想让它认识到这个属性的价值并采取行动.为此,我们需要覆盖该preFilter方法.从库存实施开始,进行一些更改:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们还需要覆盖该setRules方法,以指示过滤器使用MyAccessRule类而不是标准CAccessRule.同样,我们通过更改线来修改库存实施

$r=new CAccessRule;
Run Code Online (Sandbox Code Playgroud)

阅读

$r=new MyAccessRule;
Run Code Online (Sandbox Code Playgroud)

在创建这些类之后,我们还必须将它们注入Yii的管道中.为此,请filterAccessControl在基本控制器类上覆盖; 再次,将股票实施作为参考并进行一些小改动:

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

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

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

选项2:在每个操作中实现访问控制(要避免)

如果你不舒服的子类Yii中的核心部件,另一种选择,我不建议是嵌入要保护或覆盖的每个控制器动作内都访问控制和重定向逻辑beforeAction方法在你的控制器涵盖了从一个多个动作地点.