Django admin with FCGI + lighttpd - django

I'm running a django installation on lighttpd +FCGI.
Everything works fine except the admin.
It seems that the redirects after I post something (i.e. I modify sor create an instance of a model) go wrong.
The admin keeps redirecting me to www.xyz.com/django.fcgi/admin/... while django.fcgi should be used only by the lighttp rewrite rule to invoke FCGI.
Here's the redirection in the conf file
url.rewrite-once = (
"^(/media.*)$" => "$1",
"^/favicon\.ico$" => "/media/favicon.ico",
"^(/.*)$" => "/django.fcgi$1",
)
how can I fix this?

The admin site is trying to work out the URL to use based on the SCRIPT_NAME variable passed by lighttpd, but that's the rewritten URL, not the original one. You can force Django to use the original path by adding the following to your settings.py file.
FORCE_SCRIPT_NAME = ""
See the FORCE_SCRIPT_NAME documentation and the Django FastCGI docs for more information.

Related

Django with fastcgi and lighttpd. Admin site requests "/homepage.fcgi/homepage.fcgi/admin/"

I've been trying to deploy a simple Django website on my own Ubuntu server.
After some troubles I've finally gotten most of it to work, except some issues with URLs and the admin site.
All parts of the site designed by myself works fine, but there's an issue with the admin site. (which works fine locally with runserver btw). I have a link to "/admin/" on my own site which works, and sends me to the login for the admin site. When clicking "log in" however, i get a
404 error and:
Request URL: http://mydomain.com/homepage.fcgi/homepage.fcgi/admin/
Obviously there is something wrong with the url-rewrite. With all other links it adds "homepage.fcgi" invisibly once, but here it does it twice.
I bet there's a simple solution, but this is my first time ever deploying anything other than a pure html site..
Here is the end of my lighttpd.conf:
fastcgi.server = (
"/homepage.fcgi" => (
"main" => (
# Use host / port instead of socket for TCP fastcgi
# "host" => "127.0.0.1",
# "port" => 3033,
"socket" => "/home/myDjango/fcgi/homepage.sock",
"check-local" => "disable",
)
),
)
alias.url = (
"/static" => "/home/myDjango/static_root",
)
url.rewrite-once = (
"^(/static.*)$" => "$1",
"^(/.*)$" => "/homepage.fcgi$1",
)
Answering my own question here.
Add
FORCE_SCRIPT_NAME = ""
to settings.py.
Then restart the fcgi process.
I knew about the FORCE_SCRIPT_NAME = "" trick before posting this,
but i thought it didn't work because i didn't restart fcgi.

django socialauth twitter , google oauth , facebook does not work

This is my first post, and I have a problem I could not make it work django OMAB socialauth of three things I just need to google, facebook, and twitter, google works well with open id, but not much twitter and I put in my
settings. py:
TWITTER_CONSUMER_KEY = '00' this is no real
TWITTER_CONSUMER_SECRET = '00' this is no real
FACEBOOK_APP_ID = '' ihave no key
FACEBOOK_API_SECRET = ''
LINKEDIN_CONSUMER_KEY = ''
LINKEDIN_CONSUMER_SECRET = ''
ORKUT_CONSUMER_KEY = ''
ORKUT_CONSUMER_SECRET = ''ihave no key
GOOGLE_OAUTH2_CLIENT_ID = ''
GOOGLE_OAUTH2_CLIENT_SECRET = ''
SOCIAL_AUTH_CREATE_USERS = True
SOCIAL_AUTH_FORCE_RANDOM_USERNAME = False
SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user'
SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete'
LOGIN_ERROR_URL = '/login/error/'
#SOCIAL_AUTH_USER_MODEL = 'app.CustomUser'
SOCIAL_AUTH_ERROR_KEY = 'socialauth_error'
GITHUB_APP_ID = ''
GITHUB_API_SECRET = ''
FOURSQUARE_CONSUMER_KEY = ''
FOURSQUARE_CONSUMER_SECRET = ''
LOGIN_URL = '/login-form/'
LOGIN_REDIRECT_URL = '/'
LOGIN_ERROR_URL = '/login-error/'
I am using the example that comes in the zip of OMAB socialauth django , but not working.
When I created my twitter app, I wrote my domain www.sisvei.com , I am testing locally socialauth django ie 127.0.0.1:8000, then sign in with twitter sends me to this url:
http://127.0.0.1:8000/login/error/ and a message saying is the Incorrect authentication service
this happens with facebook and google oauth and oauth2
I'm new to django and I this much work comprising this part of django socialath hopefully help me, thank you very much.
You need to be more specific on "why it doesn't work". Where are you getting the errors?
When debugging a third-party oauth/openid app in Django, generally it boils down to:
configuration & keys - did you make sure to obtain all of the necessary API keys for the services you will be using, and to add them to your configuration?
urls - did you remember to add the necessary urlpatterns to your base urls.py file?
authentication setup on the server - often, you'll need to have a file available or respond with a specific header when the authentication service hits your server. Have you checked to make sure that is set up?
databases - have you run syncdb after installing the app? Are all the tables set up?
templates - if the third party app requires you to set up templates, do you have them set up?
custom views - are you using custom views? If so, try using the built-in views that came with the third party app first, to see if they work
After those are confirmed, you're going to want to be able to see what requests are taking place. Use the debugger included in Chrome/Safari, or get the web developer add-on for Firefox, and look at the network requests as they happen. Do you see HTTP responses other than 200 (say, 404, 500, 403, etc?) those mean that the services aren't responding correctly.
From your error, it looks like you have not correctly set up your callback URL on Twitter. It should be sending you to www.sisvei.com, not 127.0.0.1. Alternatively, check the URL when you get to the Twitter login page -- is the callback URL in the URL, and is it pointing to 127.0.0.1? Then Django is sending it the wrong callback URL.
Finally this:
I wrote my domain www.sisvei.com python does not support this
Is unclear. As far as I know, Python doesn't care what the domain is.
WAIT A MINUTE ...
Are you using runserver? Are you getting the following error?
Error: "www.sisvei.com" is not a valid port number or address:port pair.
If so, there is an easy fix! Just run it like so:
python manage.py runserver www.sisvei.com:80
That should resolve your error if that's what's happening. You're probably running it as
python manage.py runserver 127.0.0.1
127.0.0.1 is a reserved IP address that points back to localhost, your own computer. As a result, it is not possible to use it for authentication or any other purpose outside of programs running on your own machine. See this article for more info.
I'm not sure, but I might be having similar problems, oscar. For me, SocialAuth was generating an AuthenticationURL for facebook, foursquare and hotmail, but not for google, twitter or any of the other address it supports. I think it may be something wrong with the API, so I posted an issue on the social-auth google group...you may want to check there to see if anyone updates!!
https://code.google.com/p/socialauth/issues/detail?id=282&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary%20Modified

How to enable https in Django-auth generated pages?

Using the Django-auth application (Django version 1.3), I want to have my login page go to https://mysite.com/login/. Currently, I'm using:
# urls.py
from django.contrib.auth.views import login
urlpatterns = patterns('', url(r'^login/$', login, name='login-view'),)
# navbar.html
<li id="nav-login"><a href="{% url login-view %}" ><b>Login</b></a></li>
which works nicely, but goes to http://mysite.com/login/.
Is there some way to tell Django-auth what prefix (https) to use, when it reverses the view name? I've read the entire manual page, and haven't found anything that covers it. Or maybe some way to tell the url tag to go to https?
Or is the only option to specify the entire URL manually? I hope not :) And given how powerful Django has been so far, I can't believe it wouldn't have that ability - I must be overlooking it. :)
Set OS environmental variable HTTPS to on
You need to enable the OS environmental variable HTTPS to 'on' so django will prepend https to fully generated links (e.g., like with HttpRedirectRequests). If you are using mod_wsgi, you can add the line:
os.environ['HTTPS'] = "on"
to your wsgi script. You can see the need for this by reading django/http/__init__.py:
def build_absolute_uri(self, location=None):
"""
Builds an absolute URI from the location and the variables available in
this request. If no location is specified, the absolute URI is built on
``request.get_full_path()``.
"""
if not location:
location = self.get_full_path()
if not absolute_http_url_re.match(location):
current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
self.get_host(), self.path)
location = urljoin(current_uri, location)
return iri_to_uri(location)
def is_secure(self):
return os.environ.get("HTTPS") == "on"
Secure your cookies
In settings.py put the lines
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
and cookies will only be sent via HTTPS connections. Additionally, you probably also want SESSION_EXPIRE_AT_BROWSER_CLOSE=True. Note if you are using older versions of django (less than 1.4), there isn't a setting for secure CSRF cookies. As a quick fix, you can just have CSRF cookie be secure when the session cookie is secure (SESSION_COOKIE_SECURE=True), by editing django/middleware/csrf.py:
class CsrfViewMiddleware(object):
...
def process_response(self, request, response):
...
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None)
Direct HTTP requests to HTTPS in the webserver
Next you want a rewrite rule that redirects http requests to https, e.g., in nginx
server {
listen 80;
rewrite ^(.*) https://$host$1 permanent;
}
Django's reverse function and url template tags only return relative links; so if you are on an https page your links will keep you on the https site.
As seen in other StackOverflow questions, you could implement middleware that would automatically redirect the login page to a secure version.
If you are really serious about security, you should probably migrate the entire website to SSL. From the EFF's How to Deploy HTTPS Correctly:
You must serve the entire application domain over HTTPS. Redirect HTTP requests with HTTP 301 or 302 responses to the equivalent HTTPS resource.
Some site operators provide only the login page over HTTPS, on the theory that only the user’s password is sensitive. These sites’ users are vulnerable to passive and active attack.

Django Request URL becomes weird

I have a django project running on my localhost and it is working very well, however when I uploaded it to real server, some problem started happening with the url. it happens every time HttpResponseRedirect or any redirect gets called
a page on my local host
http://127.0.0.1:8000/signin
while on the server it becomes
http://xyz.com,%20xyz.com/signin
in firebug i see
GET signin 301 MOVED PERMANENTLY
GET signin http://xyz.com,%20xyz.com/signin
I belive this happens because the urls.py has ^signin/$^ and APPEND_SLASH = True in settings.py because when I visit /signin/ it works!
404 page on my local host
Request URL: http://127.0.0.1:8000/test
on the server
Request URL: http://xyz.com,%20xyz.com/test
for some reason it is adding [comma][space] to url and redirects it.
home page is working without issues
The issue is tracked in the following ticket:
https://code.djangoproject.com/ticket/11877
It has to do with how Django handles proxy redirection. The following middleware will help you out.
class MultipleProxyMiddleware(object):
FORWARDED_FOR_FIELDS = [
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED_HOST',
'HTTP_X_FORWARDED_SERVER',
]
def process_request(self, request):
"""
Rewrites the proxy headers so that only the most
recent proxy is used.
"""
for field in self.FORWARDED_FOR_FIELDS:
if field in request.META:
if ',' in request.META[field]:
parts = request.META[field].split(',')
request.META[field] = parts[-1].strip()
If, for example, your Django site is sitting behind a proxy which includes proxy information in the X-Forwarded-For header, and then your web server also does proxying, the header will contain a list (comma separated) of the proxied addresses. By using this middleware, it will strip all but one of the proxied addresses in the headers.
It might not be an answer since I'm working with you on the same application, I fixed it.
It has something to do with nginx to apache redirection, we had proxy_set_header Host $host; and when I disabled it the redirection worked without errors.

Multiple installs of Django - How to configure transparent multiplex through the webserver (Lighttpd)?

This question flows from the answer to:How does one set up multiple accounts with separate databases for Django on one server?
I haven't seen anything like this on Google or elsewhere (perhaps I have the wrong vocabulary), so I think input could be a valuable addition to the internet discourse.
How could one configure a server likeso:
One installation of Lighttpd
Multiple Django projects running as FastCGI
The Django projects may be added/removed at will, and ought not to require restarting the webserver
Transparent redirection of all requests/responses to a particular Django installation depending on the current user
I.e. Given Django projects (with corresponding FastCGI socket):
Bob (/tmp/bob.fcgi)
Sue (/tmp/sue.fcgi)
Joe (/tmp/joe.fcgi)
The Django projects being started with a (oversimplified) script likeso:
#!/bin/sh
NAME=bob
SOCKET=/tmp/$NAME.fcgi
PROTO=fcgi
DAEMON=true
/django_projects/$NAME/manage.py runfcgi protocol=$PROTO socket=$SOCKET
daemonize=$DAEMON
I want traffic to http://www.example.com/ to direct the request to the correct Django application depending on the user that is logged in.
In other words, http://www.example.com should come "be" /tmp/bob.fcgi if bob is logged in, /tmp/joe.fcgi if joe is logged in, /tmp/sue.fcgi if sue is logged in. If no-one is logged in, it should redirect to a login page.
I've contemplated a demultiplexing "plexer" FastCGI script with the following algorithm:
If the cookie $PLEX is set, pipe request to /tmp/$PLEX.fcgi
Otherwise redirect to login page (which sets the cookie PLEX based on a many-to-one mapping of Username => PLEX)
Of course as a matter of security $PLEX should be taint checked, and $PLEX shouldn't give rise to any presumption of trust.
A Lighttpd configuration would be likeso (though Apache, Nginx, etc. could be used just as easily):
fastcgi.server = ( "plexer.fcgi" =>
( "localhost" =>
(
"socket" => "/tmp/plexer.fcgi",
"check-local" => "disable"
)
)
)
Input and thoughts, helpful links, and to know how to properly implement the FastCGI plexer would all be appreciated.
Thank you.
Here's roughly how I solved this:
In lighttpd.conf
$SERVER["socket"] == "localhost:81" {
include_shell "/opt/bin/lighttpd_conf.py"
}
And corresponding lighttpd_conf.py:
#!/usr/bin/python
import fileinput
ACCOUNT_LIST_FILE = "/opt/servers/account_list.txt"
for user in fileinput.input(ACCOUNT_LIST_FILE):
print """
$HTTP[\"url\"] =~ \"^/%s/\" {
scgi.server = ( \"/\" =>
(
(
\"socket\" => \"/tmp/user-socket-%s.scgi\",
\"check-local\" => \"disable\",
)
)
)
}
""" % (user, user)
Where ACCOUNT_LIST_FILE contains a number of accounts, e.g.
abc1
abc2
abc3
The server will map http://example.com/abc1 to /tmp/user-socket-abc1.scgi, where presumably a Django instance for user abc1 is talking SCGI.
One must obviously perform some sort of taint checking on the names of accounts (I generate these).