Перенаправить правила доступа с помощью Yii - PullRequest
9 голосов
/ 21 марта 2012

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

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

В первом правиле действия «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. 

... для аутентифицированных пользователей, когда они пытаются получить доступ к этим действиям. Вместо этого я хочу перенаправить их на другую страницу. Было бы полезно, если бы я мог сделать что-то подобное в первом правиле

array('redirect',
    'actions'=>array('index','register','login','password'),
    'users'=>array('@'),
    'url'=>array('home/index'),
    ),

Ответы [ 4 ]

28 голосов
/ 04 сентября 2012

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

array('deny',
'actions'=>array('index','register','login','password'),
'users'=>array('@'),
'deniedCallback' => function() { Yii::app()->controller->redirect(array ('/home/index')); }
),
23 голосов
/ 21 марта 2012

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

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

4 голосов
/ 10 июля 2013

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

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

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

'deniedCallback' => array('ClassName', 'staticMethodName'),
1 голос
/ 06 августа 2012

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

Должно быть:

if(is_array($rule->redirect) && isset ($rule->redirect[0])){
    $request->redirect($app->createUrl($rule->redirect[0]));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...