Redirect to login for guest users in every controller
#1
Posted 08 September 2011 - 11:49 PM
if(Yii::app()->user->isGuest) $this->redirect(Yii::app()->getModule('user')->loginUrl);
But to have it working in the whole site I need to put this code in every beforeAction() in every Controller!
In a backend application the guest user can not even see the app menu, a non autenticated user can only access the login page. It's a tipical scenario. Every controller should be protected for guest users.
For a backend application this behavior may be desirable for every controller, there is a way to write the code just once, in a single place, instead of adding the beforeAction() to each Controller?
#2
Posted 09 September 2011 - 01:38 AM
#3
Posted 09 September 2011 - 01:39 AM
Add the rule
array('deny', 'users'=>array('?'), ),
to your base controller (f.e. 'Controller') where all your controllers are inherited from.
See this wiki article too: Access rules to default deny
#4
Posted 09 September 2011 - 12:11 PM
But I found a little issue..
If I deny access to every non autenticated user in every controller, Yii will redirect to the login controller/action. But this controller also has the access denied! This condition creates an infinite loop of redirects to the login form.
I can avoid it explicitly allowing access to every user to the login controller, like this:
array('allow', // allow authenticated users to access all actions
'controllers'=>array('user'),
'actions'=>array('login'),
'users'=>array('*'),
),
but it doesn't work... If I just define the 'login' action (removing the "'controllers'=>array('user')," line)it works fine, but also defining the controller to narrow the rule will lead to a no-match. Maybe a sintax issue?
If I just specify the login action the system will allow access to any action called "login", no matter the related controller.
#5
Posted 11 September 2011 - 04:10 PM
I wouldn't add 'controllers' to the access rules. Maybe this helps.
#6
Posted 26 April 2012 - 03:12 AM
I have a solution, why don't you check in beforeAction() of controller.
I've tried and it works for every Guest users, they will be redirected to login page.
public function beforeAction() { if (Yii::app()->user->isGuest) $this->redirect(Yii::app()->createUrl('user/login')); //something code right here if user valided }
Hope that help.
#7
Posted 26 January 2013 - 11:21 AM
public function actionIndex() { if (Yii::app()->user->isGuest) $this->redirect(Yii::app()->createUrl('site/login')); else $this->render('index'); }
#8
Posted 26 January 2013 - 12:31 PM
We can use a behavior to to acheive the things.
Create ApplicationBehavior.php put inside the components folder.
components/ApplicationBehavior.php
<?php class ApplicationBehavior extends CBehavior { private $_owner; public function events() { return array( 'onBeginRequest'=>'denyEverything', ); } public function denyEverything() { $owner=$this->getOwner(); if($owner->user->getIsGuest()) $owner->catchAllRequest=array("site/login"); } } ?>
Then attach the behavior as a property to the application.
main.php
'behaviors'=>array( 'class'=>'application.components.ApplicationBehavior', ),
Now if user is guest all the requests are landed at site/login.
Regards.
#9
Posted 26 January 2013 - 12:38 PM
Forcing login
Pretty much what seenlvasas said.
I use a variation of this and works well. I also added something like this to my main config file to manage sessions.
'components'=>array( //forces user to login after 20 minutes of inactivity. 'session' => array( 'class' => 'CDbHttpSession', 'timeout' => 1200, ), 'user'=>array( // enable cookie-based authentication 'class' => 'WebUser', 'allowAutoLogin'=>false, 'autoRenewCookie' => true, 'authTimeout' => 86400, //kills session after 24 hours just in case above fails or if a user clicks remember me it will only last for this duration. 'loginUrl' => array('/user/login'), ),
here is my exact RequireLogin.php note i'm using yii-user and the captcha image dosen't render on login but i don't use it anyways.
<?php class RequireLogin extends CBehavior { public function attach($owner) { $owner->attachEventHandler('onBeginRequest', array($this, 'handleBeginRequest')); } public function handleBeginRequest($event) { $app = Yii::app(); $user = $app->user; $recovery = trim(is_array(Yii::app()->getModule('user')->recoveryUrl) ? Yii::app()->getModule('user')->recoveryUrl[0] : Yii::app()->getModule('user')->recoveryUrl, '/'); //gets recovery url for yii-user $registration = trim(is_array(Yii::app()->getModule('user')->registrationUrl) ? Yii::app()->getModule('user')->registrationUrl[0] : Yii::app()->getModule('user')->registrationUrl, '/'); //gets reistraion url for yii-user $captchUrl = trim(is_array(Yii::app()->getModule('user')->captchaUrl) ? Yii::app()->getModule('user')->captchaUrl[0] : Yii::app()->getModule('user')->captchaUrl, '/'); //gets captcha url for yii-user..dosen't work?!? $request = trim($app->urlManager->parseUrl($app->request), '/'); $login = trim($user->loginUrl[0], '/'); $login = trim(is_array($user->loginUrl) ? $user->loginUrl[0] : $user->loginUrl, '/'); //gets loginurl from main config file // Restrict guests to public pages. $allowed = array($login,$recovery,$registration,$captchUrl);//allows users if not logged in to view only these 4 pages you can add others like above or like array($login,'site/login'); either way works. This is easier than adding to each controller if you only want users to be able to view a few pages w/o logging in. if ($user->isGuest && !in_array($request, $allowed)) $user->loginRequired(); // Prevent logged in users from viewing the login page. $request = substr($request, 0, strlen($login)); if (!$user->isGuest && $request == $login) { $url = $app->createUrl($app->homeUrl[0]); $app->request->redirect($url); } } } ?>
My url manager also looks like this (displays urls like : myproject.com/products/create)
// uncomment the following to enable URLs in path-format 'urlManager'=>array( 'urlFormat'=>'path', 'showScriptName'=>false, 'caseSensitive'=>false, 'rules'=>array( '<controller:\w+>/<id:\d+>'=>'<controller>/view', '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>', '<controller:\w+>/<action:\w+>'=>'<controller>/<action>', ), ),
This should help someone out!
#10
Posted 20 February 2013 - 06:47 PM
In "myController" which extends "CController" I added this method:
public function beforeAction() { Yii::app()->user->setReturnUrl(Yii::app()->request->getUrl()); if (Yii::app()->user->isGuest && $this->id != "site") $this->redirect(Yii::app()->createUrl('site/login')); //optionally include code here if its an authenticated user return true; }
The differences from logos010's code are
- the "return true" at the end - this code doesn't work if you leave that out,
- checking for the current controller id to avoid an infinite loop on the redirect.
- I also assume that the login (and other non-auth pages) are under "site" so this is changed too.
- Stored the current Url into "returnUrl" so the user automagically comes back here after login
#11
Posted 15 May 2013 - 06:19 AM
your solution is working fine but i have one problem with that,
i m unable to get captcha image at login page.
do you have any solution for that plz inform me
#12
Posted 22 October 2013 - 10:19 AM
I solved the issue with following code (by checking that current request URL doesnt contain captcha word)
public function beforeAction()
{
Yii::app()->user->setReturnUrl(Yii::app()->request->getUrl());
$requestUrl=Yii::app()->request->url;
if (Yii::app()->user->isGuest && ( strpos($requestUrl, 'captcha') == null ) )
$this->redirect(Yii::app()->createUrl('site/login'));
//optionally include code here if its an authenticated user
return true;
}
#13
Posted 23 September 2014 - 01:37 AM
The simplest way to achieve this stuff. Just add the below function in component/Controller.php
public function beforeAction(CAction $action)
{
if(!isset(Yii::app()->user->user_id) && !($action->controller->id == 'site' && $action->id == 'login'))
{
$this->redirect(array('site/login'));
}
return true;
}
No need to add the beforeAction() in every controller.
Yii::app()->user->user_id
Here user_id can be any session variable.
#14
Posted 29 May 2015 - 05:34 AM
after 'components' =>[],
'as beforeRequest' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['@'],
],
],
],
#15
Posted 24 February 2016 - 04:01 AM
I presume the above solutions will redirect all pages to login for a guest user? What if you have some pages that don't require a login first? In that case would we need to put a check on each controller?
#16
Posted 14 September 2016 - 01:45 AM
public function beforeAction($action) { if (Yii::app()->user->isGuest && Yii::app()->controller->action->id != "login") { Yii::app()->user->loginRequired(); } //something code right here if user valid return true; }
site controller only needs Yii::app()->controller->action->id != "login" this condition. remove it for another controllers
#18
Posted 30 November 2016 - 02:16 AM
If you allow
Me multiple users each user has specific powers
Is there a way to do it
By User Type
Types of user = 1,2,3,4
in yii1
#19
Posted 21 December 2016 - 02:29 AM
#20
Posted 21 December 2016 - 02:31 AM
