7

Running Django 1.2.5 on a Linux server with Apache2 and for some reason Django seems like it cannot store CSRF or Session cookies. Therefore when I try to login to the Django admin it gives me a CSRF verification error upon submitting the login form. Has anyone come up against this and found a solution?

I AM able to make a valid post when i try this at the url of my VPS that was provided by my host. Example: vps123.hostdomain.com/admin/ and for that domain the cookies DO get set. However, when I go to www.sitedomain.com/admin/ and try to login I get a CSRF 403 error saying the cookie is not there and when I check in my browsers cookies they are not set.

I have tried setting the following in my settings file:

SESSION_COOKIE_DOMAIN = 'www.sitedomain.com'
CSRF_COOKIE_DOMAIN = 'www.sitedomain.com'

Also tried:

SESSION_COOKIE_DOMAIN = 'vps123.hostdomain.com'
CSRF_COOKIE_DOMAIN = 'vps123.hostdomain.com'

I have 'django.middleware.csrf.CsrfViewMiddleware' added to my MIDDLEWARE_CLASSES in settings.py and there is a CSRF token in the form and it shows up in the POST.

I have cookies enabled. I have tried this on multiple browsers and machines.

There is a varnish proxy server sitting in front of www.sitedomain.com that I think may be part of the problem. Anyone with experience using proxy servers and Django may be able to shed some light on that.

My apache2 config:

NameVirtualHost *:80

<VirtualHost *:80>
    ServerName www.sitedomain.com
    ServerAlias www.sitedomain.com
    <Location "/">
        Options FollowSymLinks
        SetHandler python-program
        PythonInterpreter nzsite
        PythonHandler django.core.handlers.modpython
        PythonDebug On
        PythonPath "['/var/www/django_projects', '/var/www', '/usr/lib/python2.6/dist-packages'] + sys.path"
        SetEnv DJANGO_SETTINGS_MODULE project_one.settings
    </Location>
    <location "/phpmyadmin">
        SetHandler None
    </location>
</VirtualHost>

<VirtualHost *:80>
    ServerName othersite.sitedomain.com
    ServerAlias othersite.sitedomain.com
    <Location "/">
        Options FollowSymLinks
        SetHandler python-program
        PythonInterpreter ausite
        PythonHandler django.core.handlers.modpython
        PythonDebug On
        PythonPath "['/var/www/django_projects', '/var/www', '/usr/lib/python2.6/dist-packages'] + sys.path"
        SetEnv DJANGO_SETTINGS_MODULE project_two.settings
    </Location>
    <location "/phpmyadmin">
        SetHandler None
    </location>
</VirtualHost>
Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
thomallen
  • 1,926
  • 1
  • 18
  • 32

3 Answers3

3

The problem was that I have a Varnish Proxy server in front of my site. Varnish was taking requests and stripping cookies from them. To fix this I had to have the company that is managing the Varnish Server add '/admin' to a list of exceptions so that cookies could be passed. Sorry I can't shed more light on how the Varnish process works.

thomallen
  • 1,926
  • 1
  • 18
  • 32
  • oh that's interesting! Was it only the admin site that wasn't successfully working with CSRF? I'd also imagine that any future URLs that have forms will need to be added to the exception list. Can I suggest editing the title of your question to include the word varnish proxy so future users suffering this problem are able to find this answer easily? – Josh Smeaton May 24 '11 at 00:27
2

Are you including the {{csrf_token}} in your form template?

<form autocomplete="off" method="post" action="{% url auth_login %}">{% csrf_token %}
    {{form|as_p}}
    <input type='submit' />
</form>

And including the middleware?

    'django.middleware.csrf.CsrfViewMiddleware',

From your edit, at a guess, it might have something to do with the VirtualHost configuration in Apache (if your provider is using apache). Here is an edited version of one of my apache configurations.

<VirtualHost *:80>
ServerName www.domain.com

WSGIProcessGroup my-django-site
WSGIScriptAlias / /path-to-my-django-site/wsgi/production.wsgi
Alias /media /path-to-my-django-site/media
</VirtualHost> 

It may be the case that the server name within apache has to match the domain name you are hitting the box at, along with the *_COOKIE_DOMAIN settings in your Django configuration. I'm not sure if you'll be able to change this though. Might be worth speaking to your provider if no other answers yield a win.

Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
0

Are you updating your template data with the csrf info?

from django.core.context_processors import csrf

def index(request)
    data = {"listitems": items}
    data.updates(csrf(request))

    return render_to_response('template.html', data)
Stuart Grimshaw
  • 1,541
  • 1
  • 18
  • 41