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','url'=>array('home/index'),
从Yii v1.1.11开始CAccessRule定义了deniedCallback
属性,可轻松允许您在访问被拒绝时定义重定向.我不想偷Iain Gray’s thunder,所以去upvote他的答案(感谢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); }
而已!现在,您可以通过向访问控制过滤器提供新的重定向参数,从而在任何控制器中利用额外的功能:
public function accessRules() { return array( array('deny','redirect'=>array('home/index'),); }
选项2:在每个动作内部实现访问控制(要避免)
如果您对Yii的核心组件进行子类化并不舒服,我不建议的另一个选项是将要保护的每个控制器操作中嵌入访问控制和重定向逻辑,或者覆盖控制器上的beforeAction
方法以覆盖多个操作一个位置