Different sessions for admin and applications in Django
Asked Answered
L

4

15

I'd like to have different sessions for the Django admin interface and applications themselves to be able to login as admin to the admin interface and as a standard user to the application.

Any ideas how to achieve that?

P.S. Sure, I can use 2 different web browser instances, any other ways?

Litch answered 5/10, 2010 at 10:44 Comment(3)
Sounds interesting because it should also give you the opportunity to view frontend/backend in different languages...Maker
I doubt this is possible using django.contrib.auth, I expect you'd have to write your own solution, which is going to be a lot more work than just using 2 different browser instances (or using your browser's private mode e.g. Chrome Incognito - google.com/support/chrome/bin/answer.py?hl=en&answer=95464).Versicle
It should ne possible to get this working with using different session cookies / session keys for front- and backend... I guess you would have to make your own session middleware, that checks if it's an admin request or not and handles two different cookies...Maker
H
10

The way I have solved this in the past is to have 2 different urls. www.example.com and admin.example.com. As the sessions are stored in cookies, and the cookies being domain specific you can use both at the same time.

Heedful answered 15/1, 2011 at 19:54 Comment(3)
This is a good solution that requires little hackery outside the urls.py setup and a subdomain in your DNS zone file!Maryjomaryl
If this answered your question, please mark it as the answer, if it didn't please ask any follow up questions and I'll follow up.Heedful
In production it's most elegant way.Litch
M
7

Just wanted to encourage the usage of Bernhard Vallant's proposed solution. It takes 10minutes to implement and test. Just grab the SessionMiddleware implementation make your own version of it replacing the settings.SESSION_COOKIE_NAME depending the request path starts with admin url or not and replace the django.contrib.sessions.middleware.SessionMiddleware middleware with your new one in your settings.py

import time
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date
from django.utils.importlib import import_module
class AdminCookieSessionMiddleware(object):

    def cookie_name(self, request):
        if request.path.startswith(u'/admin'):
            return settings.ADMIN_SESSION_COOKIE_NAME
        return settings.SESSION_COOKIE_NAME

    def process_request(self, request):
        engine = import_module(settings.SESSION_ENGINE)
        session_key = request.COOKIES.get(self.cookie_name(request), None)
        request.session = engine.SessionStore(session_key)

    def process_response(self, request, response):
        """
        If request.session was modified, or if the configuration is to save the
        session every time, save the changes and set a session cookie.
        """
        try:
            accessed = request.session.accessed
            modified = request.session.modified
        except AttributeError:
            pass
        else:
            if accessed:
                patch_vary_headers(response, ('Cookie',))
            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    request.session.save()
                    response.set_cookie(self.cookie_name(request),
                            request.session.session_key, max_age=max_age,
                            expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None)
        return response

and in settings.py

MIDDLEWARE_CLASSES = (
...
#'django.contrib.sessions.middleware.SessionMiddleware',
'path.to.your.AdminCookieSessionMiddleware',
... )
ADMIN_SESSION_COOKIE_NAME = 'somethingDifferentThanSESSION_COOKIE_NAME'
Melburn answered 8/12, 2014 at 16:43 Comment(3)
There is a problem with above solution though. Not all requests to admin interface are made with '/admin' prefix. For instance if you use Grappelli for admin interface your admin dynamic m2m or autocomplete lookups will go to 'site.url/grappelli/lookup. So you would need to handle that also in cookie_name method from above example becouse one would get forbidden 403 response in that case for the lookups.Melburn
there is also an issue with csrf token, forms on both admin and non admin site will use it and overwrite, so the csrf cookie name also should be varied across admin and non admin site.Melburn
Nice solution for some develop environment. By the way, I think inhreit from SessionMiddleware is better.Vtehsta
V
1

You can also achieve this with two (very slightly different) settings files, each having a different session key name:

In settings_app.py:

SESSION_COOKIE_NAME = 'mysite_app'

In settings_admin.py:

SESSION_COOKIE_NAME = 'mysite_admin'

I've found it useful to have different urls.py files too; while not strictly necessary, it does aid with separation of concerns.

Vexed answered 26/10, 2013 at 15:23 Comment(0)
U
0

I had a similar problem with Django REST Framework, so my answer is dedicated to those who find themselves in the same situation as me.

Most likely, if you encounter a similar problem using DRF, authorization using sessions is allowed in your config. This is convenient when testing endpoints, but in most cases, in production you won’t need it, just like BrowsableAPI in principle.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # UNCOMMENT IF YOU USE BROWSABLEAPI
        # 'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        # UNCOMMENT IF YOU USE BROWSABLEAPI
        # 'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework.renderers.JSONRenderer',
    ),
}
Undermine answered 1/12, 2023 at 16:35 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.