他们会给你一个你无法拒绝的提议
从 Yii v1.1.11 开始,CAccessRule 定义了 deniedCallback 属性,它允许您在访问被拒绝时轻松定义重定向。我不想窃取Iain Gray's thunder,所以去投票他的答案(感谢commenter,他也提醒了我这一点)。
原始答案如下。
选项 1:扩展 Yii 以启用此功能(正确)
为此,我们需要编写自己的类来代替CAccessRule 和CAccessControlFilter。对于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 方法,用于覆盖一个位置的多个操作。