Rolling your own authentication in Django
For various reasons I wanted to see just what was required to roll my own basic authentication using Django. I am aware there’s a built-in authentication module, django.contrib.auth, but it’s overkill for my ultimate goal and it depends on the session module in ways that only further study can reveal. I heard rumours that the authentication module would be pluggable. The only pluggable aspect of it that I found was the backend (i.e. the data model).
In the end the most relevant reason for doing this was that I wanted to
So, what’s involved in it? It turns out, not much!
First I created a middleware class that extracts the authentication credentials (read username and password) and sticks a ‘user object’ in the request depending on just how successfully it does this:
from base64 import b64decode
from models import User, AnonUser, BadUser
class MiniAuthMiddleWare(object):
def process_request(self, request):
auth = request.META.get('Authorization', '') or \
request.META.get('HTTP_AUTHORIZATION', '')
if not auth:
request.user = AnonUser()
return
name, pwd = b64decode(auth[6:]).split(':')
try:
u = User.objects.get(name=name)
if pwd != u.passwd:
request.user = BadUser()
return
request.user = u
return
except User.DoesNotExist, e:
request.user = BadUser()
except AssertionError, e:
request.user = BadUser()
return
The model related to this is rather minimal:
from django.db import models
class User(models.Model):
name = models.CharField(maxlength=50, primary_key=True)
passwd = models.CharField(maxlength=50)
def is_authenticated(self):
return True
class AnonUser:
name = 'Anonymous'
passwd = 'NoPass'
def is_authenticated(self):
return False
class BadUser:
name = 'BadUser'
passwd = 'NoPass'
def is_authenticated(self):
return False
Then I decorated the functions/urls that required authentication with the following:
def _RequireAuthorization(func):
def _wrapper(request):
if not request.user.is_authenticated():
response = HttpResponse()
response.status_code = 401
response['WWW-Authenticate'] = 'Basic Realm="Silly Realm"'
return response
else:
return func(request)
return _wrapper
That all seems to work just fine
![[Digg]](http://therning.org/magnus/wp-content/plugins/bookmarkify/digg.png)
![[Reddit]](http://therning.org/magnus/wp-content/plugins/bookmarkify/reddit.png)
therning.org/ magnus » Django is cute:
[...] Building on my simple authentication middleware I added a second decorator that extract argument out of the URL and passes them to the function as regular arguments: [...]
4 September 2006, 10:20 pmHugh Bien:
Nice. For a few of my projects, I decided to roll my own authentication too. Here’s another quick walkthrough on how to write your own authentication system for Django.
28 February 2008, 6:54 pm