Changes
Title
unchanged
[Guide] How to actually separate Frontend (User) and Backend (Admin) on Yii2 Advanced
Category
unchanged
How-tos
Yii version
unchanged
Tags
unchanged
yii2, user, auth, cookie, session, request, different, separate, backend, frontend, app, advanced, domain, login, autologin, CSRF, temp, cache, admin, user, member, system
Content
changed
#[Guide] How to actually separate Frontend and Backend on Yii2 Advanced#
---
I am writing this guide because I struggled to find a resource that included ALL of the necessary steps to completely separate the frontend from the backend. After reading guides like [Configuring different sessions for backend and frontend in yii-advanced-app](http://www.yiiframework.com/wiki/686/configuring-different-sessions-for-backend-and-frontend-in-yii-advanced-app/) and [yii2 configuring different sessions for backend and frontend in yii advanced application template](http://www.yiiframework.com/wiki/767/yii2-configuring-different-sessions-for-backend-and-frontend-in-yii-advanced-application-template/), there are still steps missing. It is funny how the 2nd one says it is an extension of the first one's article. So I guess, my wiki guide here is yet a 3rd and more complete extension of both of them. I also found a few StackOverflow questions and blog posts regarding this topic. None of them fully worked, and must be missing some magic sauce!
####Tip####
> Tip: For testing, use another browser and it's private browsing feature. I use Chrome as my default browser, and during testing I open Firefox in private browsing mode. This way, I can close the browser and all cookies are gone. I don't have to worry about clearing history, cache, cookies, etc.
##
## Problem
####
Say you have a 'user' table for frontend and you want an 'admin' table for backend. You think you just have to duplicate /common/models/User.php and name it Admin.php, and change /common/models/LoginForm.php to AdminLoginForm, and update the references to them in the backend. Seems logical, and is only the beginning. What will happen is you login to frontend, then open a new tab and go to backend, you will be logged in as a member from the 'admin' table matching the same ID. User ID 3 will have you logged in as Admin ID 3 in the backend. If you click logout in either of them, you get logged out of both.. You get weird behaviour and it just isn't right. Now obviously, we can't have users login to the frontend and be able to manually navigate to /backend and be logged in.
After following the two guides I mentioned earlier, it still didn't work right. I was able to login individually, but the logout of the frontend gave a "400 Bad Request" error. I read that someone changed the POST of the logout to GET. That is absolutely not necessary, a bad idea, and just is not the *correct* or proper solution. The reason the logout gave a 400 error, was because of invalid CSRF parameters.
---
##
The Proper Solution
##
I am not going to walk you through installing or setting up the Yii2 Advanced Template. The docs already cover that [here](http://www.yiiframework.com/doc-2.0/guide-tutorial-advanced-app.html). So I am assuming you know how to install it and create the user table.[...]
Duplicate `/common/models/User.php` and name it `Admin.php`. Open it up, and change the name of the class from 'User' to 'Admin'. You also need to change the `tableName()` function to `return '{{%admin}}'`.
#### Truncated example of /common/models/Admin.php:
####
```php
class Admin extends ActiveRecord implements IdentityInterface
{
{
public static function tableName()
{
{
return '{{%admin}}';
}
}}
}
```
Duplicate `/common/models/LoginForm.php` and name it `AdminLoginForm.php`. Open it up, and change the name of the class from 'LoginForm' to 'AdminLoginForm'. At the bottom of the class, there is the `getUser()` function. It references the User class. Change `User::findByUsername($this->username)` to `Admin::findByUsername($this->username)`. Save the file.
###
# Truncated example of /common/models/AdminLoginForm.php:
####
```php
class AdminLoginForm extends Model
{
{
public function getUser()
{
{
if ($this->_user === false) {
$this->_user = Admin::findByUsername($this->username);
}
return $this->_user;
}
}
}
}
```
Now you need to update `/backend/controllers/SiteController.php` to use these new models. You need to change all references of 'User' to 'Admin' and 'LoginForm' to 'AdminLoginForm', in the namespaces and the code!
###
# Truncated example of /backend/controllers/SiteController.php:
####
```php
namespace backend\controllers;
use Yii;[...]
}
}
}
```
This was common sense for me. Since the backed didn't have it's own login form or model, I knew I needed to make an Admin model to use the 'admin' table in the database, and AdminLoginForm to use that Admin model (ie: Admin::findByUsername() ).[...]
In `frontend/config/main.php` you need to edit the 'user' component, and add 'session' and 'request' to the list.
#### Truncated example of /frontend/config/main.php:
####
```php
'components' => [
'user' => [
'identityClass' => 'common\models\User',[...]
'csrfParam' => '_frontendCSRF',
],
],
```
**YOU MUST REPLACE [RANDOM KEY HERE] WITH A REAL RANDOM KEY!**[...]
For the backend, it's the same thing, only we need unique values and to specify the `common/models/Admin.php` model.
#### Truncated example of /backend/config/main.php:
####
```php
'components' => [
'user' => [
'identityClass' => 'common\models\Admin',[...]
'csrfParam' => '_backendCSRF',
],
],
```
Again, use [Random.org Random String Generator](https://www.random.org/strings/) to generate the `cookieValidationKey`. **DO NOT** use the same key you generated for the frontend! You can see, the user 'identityClass' references the Admin model. Also notice the refences to backend.[...]
As long as you use different values for these, you can have as many differnet systems as you want. You could copy the "frontend" folder, and have admin, staff, members, billing, support, forum, blog. As long as you change the values to be unique in the main config of each one, you can create as many as you need. You would just need to create an alias for each one of them.
#### The End :)
####
That's it. Now your frontend and backend are completely separate. You can login to each and not have clashes with the other, or worry about other's being able to access it when they shouldn't. This is not a chincy hack, and the most proper way to do it that I have found.
##
## Credits
####
I want give special thanks to [Serge Postrash @SDKiller](https://github.com/SDKiller). Thanks again for helping me with the config values I was missing.