0

Client access the login view,

//user is properly set here  
user = auth.authenticate(username=email, password=password)  
auth.login(request,user)  

The same client which requested the login view, requests another view

// I expect the same user I logged in previously here. But I see anonymous user here.   
user = request.user

I don't know how exactly web server recognizes two different http requests (because http is connectionless) are coming from the same user. But I know that session is the concept that makes it possible.

I have MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware',...) in my settings.py

Is there something else I need to check to make this work?

-edit

I debugged a bit,
django/contrib/auth/init:login does request.session[SESSION_KEY] = user.id django/contrib/auth/init:get_user tries looking up request.session[SESSION_KEY] on next run and fails.

I need to understand what request.session is.
I thought request is something a client sends per http-request.(so it's not persistent)

** Below is my understanding, please correct me if I'm wrong **

  1. When a user logins, server assigns a unique id for a user and send it to the user.
  2. Server also stores relevant data for the id in somewhere persistent.
  3. The user sends the unique id for every subsequent http-request.(this is cookie)
  4. Django looks up data stored in step 2(or in other cases) with the id given.
  5. Django puts the data in request.session and give to view.

I followed Django, request.user is always Anonymous User

I suspect all this is due to my custom authentication backends copied from http://www.micahcarrick.com/django-email-authentication.html

My First View.

@csrf_exempt
def login(request):
    # import pdb                                                                                                                                                                                                                                                                
    # pdb.set_trace()                                                                                                                                                                                                                                                           

    email = request.POST['email']
    password = request.POST['password']

    user = auth.authenticate(username=email, password=password)
    # auth.logout(request)                                                                                                                                                                                                                                                      

    if user is not None and user.is_active:
        auth.login(request, user)

        profile = user.get_profile()
        user_dict = profile.to_dict()

        jsonUser = json.dumps(user_dict, ensure_ascii=False, cls=DjangoJSONEncoder)
        return HttpResponse(jsonUser)
    else:
        raise Http404

My second view.

@csrf_exempt
def user_update(request):
    import pdb
    pdb.set_trace()

    user = request.user

=>  if not user.is_authenticated():
        raise Http404  // always ends up here

    print 'in user_update'
.......

MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', )

my Backends

from django.contrib.auth.models import User, check_password

class EmailAuthBackend(object):
    """                                                                                                                                                                                                                                                                         
    Email Authentication Backend                                                                                                                                                                                                                                                

    Allows a user to sign in using an email/password pair rather than                                                                                                                                                                                                           
    a username/password pair.                                                                                                                                                                                                                                                   
    """

    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        print 'getting an user for user_id: ', user_id
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
Community
  • 1
  • 1
eugene
  • 39,839
  • 68
  • 255
  • 489
  • You should show more of your second view. – Daniel Roseman Nov 20 '12 at 11:53
  • And your *full* MIDDLEWARE_CLASSES setting. – Daniel Roseman Nov 20 '12 at 12:01
  • @DanielRoseman: I added them. – eugene Nov 20 '12 at 12:06
  • Is the cookie set properly and stored in the db? – maulik13 Nov 20 '12 at 12:26
  • @maulik13: how do I see that? actually the client is android app, should I set something to enable cookie as we enable cookie for browsers? – eugene Nov 20 '12 at 13:40
  • You have to use a tool like Firebug in Firefox and check the http headers in "Net" tab in Firebug. And look for a cookie called sessionid. Match the value against database django_session. – maulik13 Nov 20 '12 at 14:49
  • Oh I missed your rest of the comment. Not sure about Android app :) – maulik13 Nov 20 '12 at 16:19
  • You should probably look at request.COOKIE object to see if you are receiving the session cookie correctly on Django side or not. – maulik13 Nov 20 '12 at 16:30
  • 1
    @maulik13: turned out it's indeed client issue. I changed my code to share one HttpClient object for all requests and it's working correctly now. Thanks for help though! – eugene Nov 21 '12 at 02:04
  • I can accept your answer if you mention checking client-side settings. – eugene Nov 21 '12 at 02:05
  • I have added that to my answer. Just for curiosity, on the android client using single instance of HttpClient stores/sends cookie correctly now? – maulik13 Nov 21 '12 at 08:51
  • maulik13: yes.. for example, look at the answer by Christian here http://stackoverflow.com/questions/3562213/httpclient-post-session-issue-how-do-i-know-if-session-has-been-created – eugene Nov 21 '12 at 08:54

1 Answers1

0

You are right about http being stateless. However using cookie can help you maintain state of the request. When you call login function Django will save the user ID (encrypted value) in the cookie named sessionid. So the next time you get a request from the user, the browser will also send this cookie in the request header.

If you look at the table named *django_session* you should see an entry where session_key has the same value as cookie sessionid.

AuthenticationMiddleware keeps track of a user authentication and assigns user object to request.user

SessionMiddleware tracks session data for a user

That's how Django will track a user and its session.

If you really want to look into details you could have a look at authentication middleware code (django.contrib.auth.middleware), especially process_request to check how a user is added in request object.

Perhaps this is useful in debugging your issue?

EDIT:

Based on what helped Eugene from the comments.

When it's session related issue (login or session data) it's a good idea to check if the cookie is set properly on the client side. If it's a desktop browser, a tool like Firebug can be helpful by reading the http headers in "Net" tab of Firebug.

In Eugene's case it's an Android client, so one option is to debug Django middleware to check the values for request.COOKIE. If you are not receiving right cookies on Django end then the cookie is not set properly on the client side. One of the reasons for this on a browser is cookies could be disabled.

So it's a good idea to check client side settings to make sure cookies are stored and sent correctly.

maulik13
  • 3,656
  • 1
  • 25
  • 36