Tuesday, April 29, 2014

After posting an ajax login form successfully, randomly user is still anonymous

Hello to everyone.

I'm experiecing a weird problem. I have an ajax form used to log users in, with username and a password and I use the jquery ajax form plugin. The django view is more or less like many others you can see everywhere: given the right username and password I call the "authenticate" and "login" functions. Then I also write a record in the table "access_users" to register the access. The response is a template that, if the user is logged in (using {% if user.is_authenticated %}), do a window.setTimeout with a window.location = "/" (that is it reloads the whole page with things for logged users).

I can assure you that username and password were rights. I checked that the template's response was for logged ones, I could see the record in "access_users". It's like if the browser doesn't accept cookies.... but it does! So when reloading the whole page (because it got the "setTimeout" thing in the response).... the new page is still for anonymous users and still asking for user and password. If the user retries to login he is inside a sort of infinite loop. Only sometimes he gets the login working finally.

I can't replicate the problem. This happens only on production environment. RANDOMLY. I mean it's almost always ok.... but when it happens for some users, it seems it happens for some other users too, but not for everyone! If it happens for one user, that user sometimes can't login from other devices too, sometimes can.

I created a script test running every 15 minutes to test the login using the "requests" library.

* First it calls the login view (like the ajax form)
* Then asserts the response contains the "setTimeout" (given only for authenticated users)
* Then it calls a page the has a sort of empty response if the user is anonymous, otherwise if granted access
* Note: I added in the headers {"X-Requested-With" : "XMLHttpRequest"} just because my views want only ajax calls

#http://docs.python-requests.org/en/latest/user/quickstart/

import requests, traceback, StringIO

sessionid = ""
sessionid2 = ""

try :
    r = requests.post("http://www.mydomain.com/mylogin/",
                      data = {'username': 'myusername', 'password': 'mypassword'},
                      headers = {"X-Requested-With" : "XMLHttpRequest"})

    assert r.status_code == 200

    sessionid = r.cookies["sessionid"]
   
    assert "setTimeout" in r.text #User not validated

    r2 = requests.get("http://www.mydomain.com/mypage/?param=400",
                      headers = {"X-Requested-With" : "XMLHttpRequest"},
                      cookies = r.cookies) #Richiesta home page per soli utenti loggati

    assert r2.status_code == 200

    sessionid2 = r2.cookies["sessionid"]
   
    assert r2.text != '\n\n<div class="cms_content cms_page">\n\t\n</div>' #Text for anonymous users

except :

    f = StringIO.StringIO()
    traceback.print_exc(file=f)

    .... send me email with sessionid and sessionid2

The script proved to me that, getting an exception in the last assert, sessionid and sessionid2 are the same! Looking at the django_sessions table, that session is anonymous in the session_data field (it hasn't any "_auth_user_id" key). And I couldn't find any other newer django session authenticated for that user in the table.

Running on Debian 6 + Apache with mod_wsgi
Django: 1.2.5
JQuery: 1.8.2
JQuery Form plugin: 3.18

The login views is this

@ajax_test
@render_to("ec/ajax/dialog/login.html")
def web_login_ec(request):
   
    validation_error = False
   
    form = LoginForm()
    if request.POST :
        form = LoginForm(request.POST)
        if form.is_valid() :
            fcd = form.cleaned_data
           
            e2cutente = E2CUtenti.objects.filter(cod_utente_ecom = fcd["username"], des_password = hashlib.md5(fcd["password"]).hexdigest())
           
            if e2cutente.count():
                e2cutente = e2cutente[0]
           
                if e2cutente.flg_abilitato == '1':
                   user = e2cutente.create_django_user(fcd["password"]) #This gives me back an auth_user record (it was already created, just read back)
                   
                   user = authenticate(username = user.username, password = fcd["password"])
                       
                    if user is not None :
                        login(request, user)
                        e2cutente.dat_ult_accesso = datetime.datetime.now()
                        e2cutente.save()
                        AccessiUser.objects.create(cod_utente_ecom = fcd["username"],
                                                   cod_clifor = e2cutente.cod_clifor if e2cutente.ind_clifor == defs.IND_CLIFOR_CLIENTE else None,
                                                   cod_age = e2cutente.cod_clifor if e2cutente.ind_clifor == defs.IND_CLIFOR_AGENTE else None,
                                                   ipaddress = request.META.get('REMOTE_ADDR', ''),
                                                   user_agent = request.META.get('HTTP_USER_AGENT', None),
                                                   session_key = request.session.session_key
                                                   )
                    else :
                        validation_error = 2
                else :
                    validation_error = 1
            else :
                validation_error = 2
   
return {"form" : form,
            "validation_error" : validation_error
            }


So I check E2CUtenti (another users table) with the username and password given by the user. Then I get the auth_user record via "User.objects.get(username = username". The user is not None in my case. I got authenticated and then logged and then AccessiUser written.

Thank you in advance for any help and suggestion.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/a08fc4ae-9ba5-4bf6-9324-ed33a492e9da%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment