yii2-usuario icon indicating copy to clipboard operation
yii2-usuario copied to clipboard

How to permit backend only to administrators?

Open robsch opened this issue 4 years ago • 5 comments

Using the yii2-app-advanced application template, I'd like to allow the whole backend only to administrators. I have secured the backend now, so that only the login is possible (no password reset, no registration, ...). For that I'm using the this application configuration (backend/config/main.php), so I don't have to declare the rules in each controller:

    'as globalAccessController' => [
        'class' => AccessControl::class,
        'rules' => [
            // the only callable action for not logged-in users
            [
                'allow' => true,
                'roles' => ['?'],
                'actions' => ['login'],
                'controllers' => ['user/security'],
            ],
            // error page should be possible anyway
            [
                'allow' => true,
                'actions' => ['error'],
                'controllers' => ['site'],
            ],
            // yii debug toolbar should always be accessible (if activated)
            [
                'allow' => true,
                'controllers' => ['debug/*'],
            ],
            // all other actions can only be called by logged-in users
            [
                'allow' => true,
                'roles' => ['@'], // 'roles' => ['administrator'] ???
            ],
        ],
    ],

Changing the last rule to 'roles' => ['administrator'] should do it. However, other users are still able to to log in though, but each page shows a 403 error page.

How can I do it the right way, so that only administrators can log in. Is it necessary to override the default SecurityController? Is there a better approach than the global access control configuration?

robsch avatar Oct 20 '21 06:10 robsch

What I've done to have the same:

  • Created a Role "WebAdmins" and assign it to users that need to have access to backend
  • in backend/config/main.php i've added the following in 'modules' part 'controllerMap' => [ 'security' => [ 'class' => \Da\User\Controller\SecurityController::class, 'on ' . \Da\User\Event\FormEvent::EVENT_AFTER_LOGIN => function (\Da\User\Event\FormEvent $event) { $roles = Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId()); foreach($roles as $k => $role){ if($k === "WebAdmins"){ \Yii::$app->controller->redirect(Yii::$app->urlManager->createUrl('')); \Yii::$app->end(); } } \Yii::$app->user->logout(true); \Yii::$app->controller->redirect(Yii::$app->urlManagerFrontend->createUrl('/user/security/login')); \Yii::$app->end(); } ], ],
  • Also here in main.php in 'components' part I've added the following 'urlManagerFrontend' => [ 'class' => 'yii\web\urlManager', 'baseUrl' => '@web/../', 'enablePrettyUrl' => true, 'showScriptName' => false, ], After user logs in the system automatically logs him out and redirects to login page on front side.

Maybe there is a better approach and will be glad to see another solutions.

P.S. the code does not formats well, but you could figure out.

EndErr avatar Oct 21 '21 05:10 EndErr

Thank you @EndErr for that. Seems to work. Just the urlManagerFronend is confusing me a bit, since I don't have a @web. Now I just use the default urlManager, so that the user gets redirected to the login page of the backend.

Little optimization that hopefully is the same as your suggestion:

'controllerMap' => [
    'security' => [
        'class' => SecurityController::class,
        'on ' . FormEvent::EVENT_AFTER_LOGIN => function (FormEvent $event) {
            $roles = Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
            if (array_key_exists(Yii::$app->modules['user']->administratorPermissionName, $roles)) {
                Yii::$app->controller->redirect(Yii::$app->urlManager->createUrl(''));
                Yii::$app->end();
            }
            Yii::$app->user->logout(true);
            Yii::$app->controller->redirect(Yii::$app->urlManager->createUrl('/user/security/login'));
            Yii::$app->end();
        }
    ],
],

btw: In order to format code, using syntax highlighting for php, use this in your postings (first and last line are essential):

```php
'controllerMap' => [
    'security' => [
        'class' => SecurityController::class,
        'on ' . FormEvent::EVENT_AFTER_LOGIN => function (FormEvent $event) {
            $roles = Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
            if (array_key_exists(Yii::$app->modules['user']->administratorPermissionName, $roles)) {
                Yii::$app->controller->redirect(Yii::$app->urlManager->createUrl(''));
                Yii::$app->end();
            }
            Yii::$app->user->logout(true);
            Yii::$app->controller->redirect(Yii::$app->urlManager->createUrl('/user/security/login'));
            Yii::$app->end();
        }
    ],
],
```

robsch avatar Nov 04 '21 10:11 robsch

for some days after a update $roles = Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId()); returns a empty array

any thoughts?

EndErr avatar Feb 26 '22 11:02 EndErr

What update? Is it related to this bug?

maxxer avatar Feb 26 '22 15:02 maxxer

not sure, just did a composer update and after that couldn't login to backend digging found that Yii::$app->user->getId() in above code returns nothing

EndErr avatar Feb 26 '22 17:02 EndErr