redirect Правила доступа с Yii

Я делаю приложение, требующее аутентификации. На странице индекса приложения я указал правила доступа, подобные этому

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'), ), 

Solutions Collecting From Web of "redirect Правила доступа с Yii"

Они сделают вам предложение, от которого вы не сможете отказаться.

Начиная с Yii v1.1.11 CAccessRule определяет свойство deniedCallback которое легко позволяет вам определять перенаправление при отказе доступа. Я не хочу воровать гром Иэна Грея , поэтому поднимите его ответ (спасибо комментатору, который также предупредил меня об этом).

Исходный ответ следует.

Вариант 1: продлить Yii, чтобы включить эту функциональность (правильно)

Для этого нам нужно будет написать собственные классы, которые будут использоваться вместо CAccessRule и CAccessControlFilter . Для CAccessRule нам просто нужно добавить одно дополнительное свойство:

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

Для 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; } } 

Затем нам также необходимо переопределить метод setRules , чтобы проинструктировать фильтр использовать класс MyAccessRule вместо стандартного CAccessRule . Опять же, мы модифицируем реализацию запаса , меняя линию

 $r=new CAccessRule; 

читать

 $r=new MyAccessRule; 

После создания этих классов мы также должны вводить их в конвейер Yii. Для этого переопределите filterAccessControl в базовом классе контроллера; снова, взяв реализацию запаса в качестве справочника и сделав небольшое изменение:

 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 на ваших контроллерах для покрытия нескольких действий с одно место.

Поскольку Yii v1.1.11 вы можете сделать то же самое с обратным вызовом и закрытием, а также только классы по умолчанию:

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

этот работал для меня с yii 1.1.11:

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

или использовать статический метод в классе:

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

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

Должно быть:

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