Они сделают вам предложение, от которого вы не сможете отказаться
Начиная с Yii v1.1.11 CAccessRule
определяет свойство deniedCallback
, которое позволяет легко определить перенаправление, когда доступ запрещен. Я не хочу красть гром Иана Грея , так что иди и проголосуй за его ответ (спасибо комментатору 1010 *, который также предупредил меня об этом).
Ниже приводится оригинальный ответ.
Вариант 1: расширить Yii, чтобы включить эту функцию (правильно)
Для этого нам нужно написать собственные классы, которые будут использоваться вместо CAccessRule
и CAccessControlFilter
. Для CAccessRule
нам просто нужно добавить еще одно свойство:
class MyAccessRule extends CAccessRule {
public $redirect; // just add this property
}
Для CAccessControlFilter
мы хотим, чтобы оно распознало ценность этого свойства и действовало в соответствии с ним. Для этого нам нужно переопределить метод preFilter
. Начиная с реализации stock * внесите несколько изменений:
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
метод на ваших контроллерах для охвата нескольких действий из одного места.