Skip to content

Instantly share code, notes, and snippets.

@r3verser
Last active December 7, 2022 08:22
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save r3verser/7cdaf9c3a4f2f631d1d1 to your computer and use it in GitHub Desktop.
Save r3verser/7cdaf9c3a4f2f631d1d1 to your computer and use it in GitHub Desktop.
Yii2 Redirects all users to login (or any) page if not logged in, but allow access to some pages (like signup, password recovery etc.)
<?php
/*
* In configuration file
* ...
* 'as AccessBehavior' => [
* 'class' => 'app\components\AccessBehavior',
* 'allowedRoutes' => [
* '/',
* ['/user/registration/register'],
* ['/user/registration/resend'],
* ['/user/registration/confirm'],
* ['/user/recovery/request'],
* ['/user/recovery/reset']
* ],
* //'redirectUri' => '/'
* ],
* ...
*
* (c) Artem Voitko <r3verser@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file https://gist.github.com/r3verser/3094c7f045af46e2f9c3807a54c91026
*/
namespace app\components;
use yii\base\Behavior;
use yii\console\Controller;
use yii\helpers\Url;
/**
* Redirects all users to defined page if they are not logged in
*
* Class AccessBehavior
* @package app\components
* @author Artem Voitko <r3verser@gmail.com>
*/
class AccessBehavior extends Behavior
{
/**
* @var string Yii route format string
*/
protected $redirectUri;
/**
* @var array Routes which are allowed to access for none logged in users
*/
protected $allowedRoutes = [];
/**
* @var array Urls generated from allowed routes
*/
protected $allowedUrls = [];
/**
* @param $uri string Yii route format string
*/
public function setRedirectUri($uri)
{
$this->redirectUri = $uri;
}
/**
* Sets allowedRoutes param and generates urls from defined routes
* @param array $routes Array of allowed routes
*/
public function setAllowedRoutes(array $routes)
{
if (count($routes)) {
foreach ($routes as $route) {
$this->allowedUrls[] = Url::to($route);
}
}
$this->allowedRoutes = $routes;
}
/**
* @inheritdoc
*/
public function init()
{
if (empty($this->redirectUri)) {
$this->redirectUri = \Yii::$app->getUser()->loginUrl;
}
}
/**
* Subscribe for event
* @return array
*/
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'beforeAction',
];
}
/**
* On event callback
*/
public function beforeAction()
{
if (\Yii::$app->getUser()->isGuest &&
\Yii::$app->getRequest()->url !== Url::to($this->redirectUri) &&
!in_array(\Yii::$app->getRequest()->url, $this->allowedUrls)
) {
\Yii::$app->getResponse()->redirect($this->redirectUri)->send();
}
}
}
@coobic
Copy link

coobic commented Feb 20, 2016

Small note from contributor:
As i can see in docs:

\Yii::$app->getResponse()->redirect($this->redirectUri);

Only add Header to Response, but not redirect user immediately to login page and asked controller still execute!
So you must add ->send() and (i don`t now why exit(0), because return true or false was not working).
Final code:

\Yii::$app->getResponse()->redirect($this->redirectUri)->send();
exit(0);

@r3verser
Copy link
Author

@coobic you are right, have added ->send(), thanks!

@LarryMarzanJr
Copy link

LarryMarzanJr commented Nov 20, 2016

@r3verser so how do we use this, tehcnically, is there any manuals?
I'm using Yii2 advanced template.
thanks

@jscuba
Copy link

jscuba commented Aug 6, 2019

@r3verser I like this, thank you. Is there a license? I see some people do this for gists: https://gist.github.com/martinbuberl/c0de29e623a1e34d1cda7e817d18bafe

@r3verser
Copy link
Author

r3verser commented Aug 6, 2019

@r3verser I like this, thank you. Is there a license? I see some people do this for gists: https://gist.github.com/martinbuberl/c0de29e623a1e34d1cda7e817d18bafe

Hi! I have updated gist to MIT license, thanks!

@strtob
Copy link

strtob commented Dec 7, 2022

Nice behavior, thank you!

to make this work with parameter urls I've changed the beforeAction as following:

$requestUrl = strtok(\Yii::$app->getRequest()->url, '?');

    if (\Yii::$app->getUser()->isGuest &&
        \Yii::$app->getRequest()->url !== Url::to($this->redirectUri) &&
        !in_array($requestUrl, $this->allowedUrls)
    ) {
        \Yii::$app->getResponse()->redirect($this->redirectUri)->send();
        exit(0);          
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment