Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django 1.2 session loss

I've asked a similar question before, but I've done some more research and this iteration should be a bit different. It seems as though several SO users have had an issue with registering and logging in users in a single view and it hasn't really been answered.

The issue is that I register, authenticate, and login a user in a single Django view. For most users that's fine, but for other users, their subsequent request (they click a link on my site) returns an Anonymous User. Somehow, the logged in user loses their session and is redirected to a page on my sit ethat doesn't require authentication.

When they then log in via a pure login view (as opposed to the register + login view), the session data stays in tact. The issue really seems to be registering and logging in a single view.

See this post for the same issue: https://stackoverflow.com/questions/1693726/problem-with-combined-authentication-login-view.

It has been suggested that this is potentially a threading issue. I've also seen it suggested that it relates to the backend for caching session data.

Any thoughts on what it really relates to? I can't reproduce the error, which is really holding me back.

EDIT--I should note that I'm using the default database backed sessions.

Here is my register/login view

def splash_register(request):
  if request.session.get('beta'):

    if request.method=='POST':
        userform=MyUserCreationForm(request.POST)
        if userform.is_valid():
            #username of <30 char is required by Django User model.  I'm storing username as a hash of user email 

            user=userform.save(commit=False)
            user.username=hash(user.email)
            user.save()



            username=user.username
            password=str(userform.cleaned_data['password'])
            user=auth.authenticate(username=username, password=password)
            if user is not None:
                auth.login(request,user)
                request.session['first_visit']=True
                return HttpResponseRedirect("/")
            else:
                return HttpResponseRedirect('/splash/register/')
        else:
            userform=MyUserCreationForm(request.POST)
            return render_to_response("website/splash_register.html", {'userform':userform}, context_instance=RequestContext(request))
    return render_to_response("website/splash_register.html", context_instance=RequestContext(request))     
else:
    return HttpResponseRedirect('/splash/')        
like image 212
Ben Avatar asked Apr 25 '11 04:04

Ben


People also ask

How to store session data in Django?

You can utilise Django’s engine to store your sessions data in a file-based system. You’ll also need to make sure that your web server has permission to read and write the directory where your sessions file is stored. 4. Through the use of cookie-based sessions

What are session keys in Django?

Django (and most of the web framework) uses sessions to maintain track of the “state” of a site and a particular browser. Sessions allow you to save any amount of data per browser and make it available to the site anytime the browser connects. Individual session data items are then referred to by a “key,” which both saves and retrieves data.

What happens if you run Django with a secret_key?

Running Django with a known SECRET_KEY defeats many of Django’s security protections, and can lead to privilege escalation and remote code execution vulnerabilities. All sessions if you are using any other session backend than django.contrib.sessions.backends.cache , or are using the default get_session_auth_hash ().

What is anonymous session in Django?

Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. Cookies contain a session ID – not the data itself (unless you’re using the cookie based backend ).


2 Answers

You don't have to use authenticate and, in this scenario, it's not really needed. All you need to do is set the backend of the user record.

So something like this would work:

def splash_register(request):
  if request.session.get('beta'):

    if request.method=='POST':
        userform=MyUserCreationForm(request.POST)
        if userform.is_valid():
            #username of <30 char is required by Django User model.  I'm storing username as a hash of user email 

            user=userform.save(commit=False)
            user.username=hash(user.email)
            user.backend='django.contrib.auth.backends.ModelBackend'
            user.save()


            username=user.username
            password=str(userform.cleaned_data['password'])
            auth.login(request, user)
            request.session['first_visit']=True
            return HttpResponseRedirect("/")
        else:
            userform=MyUserCreationForm(request.POST)
            return render_to_response("website/splash_register.html", {'userform':userform}, context_instance=RequestContext(request))
    return render_to_response("website/splash_register.html", context_instance=RequestContext(request))     
else:
    return HttpResponseRedirect('/splash/')

Update

I mentioned this in a comment, but in terms of an "answer" the solution is to add this to your settings file:

SESSION_COOKIE_DOMAIN = 'yourdomain.com'

This will allow users coming in from www.yourdomain.com or yourdomain.com to log in to the website.

like image 129
Jordan Reiter Avatar answered Jan 11 '23 00:01

Jordan Reiter


Oh man, I am both incredibly relieved and also full of self-loathing. I had no idea that that the Cookies weren't transferable between www and non-www domain names.

A set of my users were coming to www and then were redirected to non-www, killing their session. I'm setting up mod_rewrite now to resolve the situation.

like image 30
Ben Avatar answered Jan 10 '23 23:01

Ben