Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to separate Frontend & Backend to use different tables (member/admin style) #8289

Closed
CyberPunkCodes opened this issue May 5, 2015 · 17 comments

Comments

@CyberPunkCodes
Copy link

I have setup a few Yii1 sites, and another Yii2 basic site.

I am used to other systems having a "members" directory, with a "members" table (or users) and an "admin" directory using an "admin" table. I am sure many of us have seen it, and that is how I like it. I like to separate the two entirely. If there was a hole, and some malicious user was to execute things they shouldn't, they could gain access to things they shouldn't. From a security point of view, the code to do admin things shouldn't be in the same file/script that users access. This has been talked about for years, and covered by security experts.

I thought Yii2 Advanced was like this. It has a frontend and backend, which looks like user and admin sections. However, the backend uses /common/models/LoginForm, which results in the same user table. It looks like any user on frontend can simply navigate to backend and be logged in?

I have tried to separate them, but have found little help online about this.
My StackOverflow Question: http://stackoverflow.com/questions/30060571/yii2-advanced-make-backend-use-admin-table-and-admin-model

I am needing the backend to be completely separate from frontend. A logged in user on frontend should not have access to backend. The backend should use a different table ('admin') from the frontend ('user').

Since frontend uses Yii::$app->user for the frontend (users), I guess that means Yii::$app->admin for the backend (admin). I see the backend also uses Yii::$app->user, so how does it know the difference between a frontend and backend user?

If you look at my SO question, you can see that I have copied the /common/models/User model as Admin, edited the main config.. I get errors, and not sure what all I have to do to get these separated. I can't find anything in the docs to help me figure out the process. I don't have a problem copying or extending classes, I just have no idea what has to be done to pull it off. I made AdminLoginForm and referenced the Admin class instead of user, but just felt I was going further down the rabbit hole. While I do assume this would require a separate login form, I don't know if the other stuff is right (main config, Admin model, etc) so I wouldn't know if it was due to errors in other areas.

IMO it should be like this out of the box, two separate sections shouldn't share the same users. Why can't the Yii2 Advanced come with an Admin section (whether it replaces backend, or it generates frontend, backend, admin) and it's own Admin model, login form, etc. We can delete it if we don't need it. It seems like it would be a very common setup that many of us would appreciate.

My guess is the logic behind it is frontend is for non-logged in users, and backend is for logged in users. Most systems need an admin section to manage those users (add/edit/delete/reset pass) at a minimum.

@samdark
Copy link
Member

samdark commented May 5, 2015

Advanced project template is just a template and you're free to adjust it as required. There's no plan to introduce such separation by default.

@samdark samdark closed this as completed May 5, 2015
@CyberPunkCodes
Copy link
Author

I understand that it is just a template. My question still persists.

I have it kind of setup, but it just is buggy and acting weird. It must be missing something.


Steps I have done
Install Yii2 Advanced, migrate, signup on frontend to create a new user. Copy 'user' table as 'admin', rename first username to 'admin' keeping the password the same (123456 for testing). Now I have a user and admin in the database.

Duplicate /common/models/User.php to Admin.php (changing name of the class)

Duplicate /common/models/LoginForm.php to AdminLoginForm.php (changing name of the class)

Edit /backend/controllers/SiteController.php to use AdminLoginForm instead of LoginForm, as well as all references to LoginForm to AdminLoginForm.

Edit /backend/config/main.php user component to:
'components' => [
'user' => [
'identityClass' => 'common\models\Admin',
'enableAutoLogin' => true,
],
],


What is happening
Individually, I can login to frontend or backend just fine. However, once you go to one (frontend) and logout, the other side fails to login (backend), or vica-versa. I test using private browsing, so I close and re-open the browser and it works fine. Like there is something with the cookies, but each section has their own unique 'cookieValidationKey'...

I had logged in as a frontend user, opened backend.. logged out of frontend. re-logged into frontend, and it took me to the backend.. what?

If you login to backend, then open a new tab and go to frontend you are logged in as the user with that same ID. So logging into backend makes you logged in as another user in frontend. If you login to the frontend, then open new tab and go to backend, you are the also logged in (given the id number exists). So basically a logged in user can navigate to my admin panel and be logged in.

It is just acting crazy, and I assume there is something else I need to do...

What do I need to do to separate the two? Is there anything in the docs relating to any of this? I must be missing something. I understand that I probably DO need to extend something else in Yii, but the docs don't shed any light on the subject.. And Googling my issue 10 different ways, I can't seem to get anywhere.

I tried to change the user component in backend/config/main.php to 'admin' and got errors about 'User::identityClass must be set'. It didn't like the main.php not having 'user' defined.

'components' => [
    'admin' => [
        'identityClass' => 'common\models\Admin',
        'enableAutoLogin' => true,
    ],
],

It didn't like that.. I thought that since frontend and backend would both use Yii::$app->user->isGuest(), that was the problem. Since a user on the frontend, going to the backend, would technically pass the user->isGuest() check.. So backend would need it's own, like: Yii::$app->admin->isGuest().

I understand if this is the wrong section, and would gladly move it or welcome it moved. I posted here because someone with a similar issue posted in the docs section. I think the docs could use some more info on the advanced template. It says the frontend and backend are like separate apps, but they are not behaving like they are separate considering something in frontend affects the backend (being logged in on one, assumes you can be logged into the other).

@SDKiller
Copy link
Contributor

SDKiller commented May 6, 2015

@WadeShuler

Like there is something with the cookies, but each section has their own unique 'cookieValidationKey'...

To separate backend and frontend completely like you want you also need to configure different names for user identityCookie name, request csrfParam and session name.

@CyberPunkCodes
Copy link
Author

@SDKiller Thank you very much for replying! I made great headway with what you said, and searching for 'identityCookie' and other session info, I found some other pages relating to what I am trying to do (separate frontend from backend, error with them both being logged in). I wish I could have found them days ago.

Frontend main config:

'components' => [
    'user' => [
        'identityClass' => 'common\models\User',
        'enableAutoLogin' => true,
        'identityCookie' => [
            'name' => '_frontendUser', // unique for frontend
            //'path'=>'/advanced/frontend'  // correct path for the frontend app.
        ]
    ],
    'session' => [
        'name' => 'PHPFRONTSESSID',
        'savePath' => sys_get_temp_dir(),  //__DIR__ . '/../tmp',
    ],
],

Backend main config:

'components' => [
    'user' => [
        'identityClass' => 'common\models\Admin',
        'enableAutoLogin' => true,
        'identityCookie' => [
            'name' => '_backendUser', // unique for backend
            //'path'=>'/advanced/backend'  // correct path for the backend app.
        ]
    ],
    'session' => [
        'name' => 'PHPBACKSESSID',
        'savePath' => sys_get_temp_dir(),  //__DIR__ . '/../tmp',
    ],
],

This is almost there. Frontend and Backend login independently as the correct users.

I am getting an error when I try to logout of the frontend. However, I can logout of the backend without an error. Weird.

When logging out of the frontend, I get this error: Bad Request (#400)

I know it's a 400 Bad Request error, and looking at what Yii debug gives me, I can't see much.

@SDKiller
Copy link
Contributor

SDKiller commented May 7, 2015

@WadeShuler

request csrfParam

@CyberPunkCodes
Copy link
Author

@SDKiller Got it, Thank you! You just saved me loads of time. I came across guides and examples, but they seem to be missing half the info. Maybe I will create a wiki to give back to the community.

@samdark
Copy link
Member

samdark commented May 7, 2015

A wiki article is a great idea.

@CyberPunkCodes
Copy link
Author

@samdark
Copy link
Member

samdark commented May 8, 2015

Thanks! I've updated markup a bit so it now looks better with headers and color.

@cbepxpa3ym
Copy link

Looks like these changes (configuration) are not actual anymore, right? I ask because I simply installed the advanced template, and configured it to use different domains per frontend and backend (ex.: frontend.loc and backend.loc). And I am able to login/logout separately in both applications.

@CyberPunkCodes
Copy link
Author

It has always been like that. Assumed have of frontend/backend is to have them on separate domains or subdomains. Ie: admin.yoursite.com for backend and just yoursite.com for frontend.

The special config is necessary if you need or want to run them on the same domain. Such as yoursite.com and yoursite.com/admin/

Even using yii2 as expected, meaning on separate sub domains without any extra config, you still won't have a separate admin table. Your admin accounts will share the same user table, which is frowned upon in regards to security. You would have a column like 'is_admin' or use the built in column for role and assign a number for admin users.. With users sharing the same column, an SQL injection could allow a user to switch the flag and convert their user account into an admin account. While an SQL injection is still possible with a separate admin table, it just makes it a little easier on them.

If you put every option on a point scale, sharing a user table for both is a few points itself for security risks.

So you would still need minor changes to create an admin model and to point to it in your config, for your backend.

Sent from my iPhone

On Dec 14, 2015, at 12:13 PM, cbepxpa3ym notifications@github.com wrote:

Looks like these changes (configuration) are not actual anymore, right? I ask because I simply installed the advanced template, and configured it to use different domains per frontend and backend (ex.: frontend.loc and backend.loc). And I am able to login/logout separately in both applications.


Reply to this email directly or view it on GitHub.

@cbepxpa3ym
Copy link

I plan to use the advanced template to create a portal with this structure of domain/subdomain:
patient: somesite.com (search a doctor, signup/login into account to make and track appointments)
provider: provider.somesite.com (signup/login to manage doctors, appointments)
admin: admin.somesite.com (login to manage both patient and provider data)

Probably, frontend application will be used for patient, backend will be used for provider, and another one application "admin" will be created for admin. Or maybe even rename "frontend" into "patient", and "backend" into "provider". But this does not matter.

Also, I would like to have 3 tables (patient, provider, admin) and use them in authentication (the same as you suggested with user and admin).

Is not this too complicated?

@CyberPunkCodes
Copy link
Author

No a few projects ago I had 3 areas. I just copied the frontend directory and named it "mainsite" and replaced all references to it. Each section is a separate app, they just all use the same framework files. Yii is actually stored in the vendor directory. You can run virtually unlimited apps or sites from the same Yii setup. Just copy frontend or backend and rename all references to them. I am not encouraging running multie sites off the same Yii setup. But you can run each section off the same site, members, admin, mainsite, portal.. However many you need. When you use composer to update Yii, all your sections are updated to the latest version and can share common models instead of having duplicate models for each section.

What your wanting to do is fine. You will just need to alter the config to use different user models pointing to the different tables.

Sent from my iPhone

On Dec 14, 2015, at 1:20 PM, cbepxpa3ym notifications@github.com wrote:

I plan to use the advanced template to create a portal with this structure of domain/subdomain:
patient: somesite.com (search a doctor, signup/login into account to make and track appointments)
provider: provider.somesite.com (signup/login to manage doctors, appointments)
admin: admin.somesite.com (login to manage both patient and provider data)

Probably, frontend application will be used for patient, backend will be used for provider, and another one application "admin" will be created for admin. Or maybe even rename "frontend" into "patient", and "backend" into "provider". But this does not matter.

Also, I would like to have 3 tables (patient, provider, admin) and use them in authentication (the same as you suggested with user and admin).

Is not this too complicated?


Reply to this email directly or view it on GitHub.

@vaishnavi168
Copy link

I exactly want the same for backend Admin.php and for frontend user.php
I tried your settings but i got error to Array to string conversion in siteController actionLogin function to if ($model->load(Yii::$app->request->post()) && $model->login()).
Values are correctly posted. I checked it by using this Yii::$app->request->post()).
How to resolve this error array to string conversion error in actionLogin function

@SDKiller
Copy link
Contributor

That depends on your model and form. I cannot guess what exacltly comes as array from your POST.
For example, you added extra brackets for input field and username comes as array.

@klimov-paul
Copy link
Member

You may check yii2tech/project-template for actual implementation.

@CyberPunkCodes
Copy link
Author

This is an old thread, and since then I have pretty much mastered splitting the apps to handle separate user tables, and even handling sub-domains.

You can check out my repo on Github: Yii2 Members System

It already has frontend using the user table and User IdentityInterface, backend using the admin table and Admin IdentityInterface.

It also has support for sub-domains. It even has the UrlManager handled for linking to separate sub-domains (ie: site.com to sub.site.com) via a second UrlManager.

Install it and test it out. Then hack it up to suit your needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants