It turns out I needed to set the HTTP Referer header to the login page
url in the request where I post the login information.

req.add_header( 'Referer', login_url )

The reason is explained on the Django CSRF documentation -
specifically, step 4.

Due to our somewhat peculiar server setup where we use HTTPS on the
production side and DEBUG=False, I wasn't seeing the csrf_failure
reason for failure (in this case: 'Referer checking failed - no
referer') that is normally output in the DEBUG info. I ended up
printing that failure reason to the Apache error_log and STFW'd on it.
That lead me to code.djangoproject/.../csrf.py and the Referer header
fix.

Thanks to anyone who gave this a read!

On Feb 22, 2:38 pm, carl <carlfeberh...@gmail.com> wrote:
> Hi, everyone. I've searched the group site and couldn't find anything
> with this specific problem. If I missed a good discussion on this, let
> me know. The following is my problem:
>
> I'm working on a django/mod_wsgi/apache2 website that serves sensitive
> information using https for all requests and responses. All views are
> written to redirect if the user isn't authenticated. It also has
> several views that are meant to function like RESTful web services.
>
> I'm now in the process of writing a script that uses urllib/urllib2 to
> contact several of these services in order to download a series of
> very large files. I'm running into problems with 403: FORBIDDEN errors
> when attempting to log in.
>
> The (rough-draft) method I'm using for authentication and log in is:
>
> def login( base_address, username=None, password=None ):
>
>     # prompt for the username (if needed), password
>     if username == None:
>         username = raw_input( 'Username: ' )
>     if password == None:
>         password = getpass.getpass( 'Password: ' )
>     log.info( 'Logging in %s' % username )
>
>     # fetch the login page in order to get the csrf token
>     cookieHandler = urllib2.HTTPCookieProcessor()
>     opener = urllib2.build_opener( urllib2.HTTPSHandler(),
> cookieHandler )
>     urllib2.install_opener( opener )
>
>     login_url = base_address + PATH_TO_LOGIN
>     log.debug( "login_url: " + login_url )
>     login_page = opener.open( login_url )
>
>     # attempt to get the csrf token from the cookie jar
>     csrf_cookie = None
>     for cookie in cookieHandler.cookiejar:
>         if cookie.name == 'csrftoken':
>             csrf_cookie = cookie
>             break
>     if not cookie:
>         raise IOError( "No csrf cookie found" )
>     log.debug(  "found csrf cookie: " + str( csrf_cookie ) )
>     log.debug(  "csrf_token = %s" % csrf_cookie.value )
>
>     # login using the usr, pwd, and csrf token
>     login_data = urllib.urlencode( dict(
>         username=username, password=password,
>         csrfmiddlewaretoken=csrf_cookie.value ) )
>     log.debug( "login_data: %s" % login_data )
>
>     req = urllib2.Request( login_url, login_data )
>     response = urllib2.urlopen( req )
>     # <--- 403: FORBIDDEN here
>
>     log.debug( 'response url:\n' + str( response.geturl() ) + '\n' )
>     log.debug( 'response info:\n' + str( response.info() ) + '\n' )
>
>     # should redirect to the welcome page here, if back at log in -
> refused
>     if response.geturl() == login_url:
>         raise IOError( 'Authentication refused' )
>
>     log.info( '\t%s is logged in' % username )
>     # save the cookies/opener for further actions
>     return opener
>
> I'm using the HTTPCookieHandler to store Django's authentication
> cookies on the script-side so I can access the web services and get
> through my redirects.
>
> Specifically, I'm getting a 403 when trying to post the credentials to
> the login page/form over the https connection. This method works when
> used on the development server which uses an http connection.
>
> There is no Apache directory directive that prevents access to that
> area (that I can see). The script connects successfully to the login
> page without post data so I'm thinking that would leave Apache out of
> the problem (but I could be wrong).
>
> I know that the CSRFmiddleware for Django is going to bump me out if I
> don't pass the csrf token along with the log in information, so I pull
> that first from the first page/form load's cookiejar. Like I
> mentioned, this works with the http/development version of the site.
>
> The python installations I'm using are both compiled with SSL.
>
> I've also read that urllib2 doesn't allow https connections via proxy.
> I'm not very experienced with proxies, so I don't know if using a
> script from a remote machine is actually a proxy connection and
> whether that would be the problem. Is this causing the access problem?
>
> From what I can tell, the problem is in the combination of cookies and
> the post data, but I'm unclear as to where to take it from here.
>
> Any help would be appreciated. Thanks

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to