views:

94

answers:

1

Because I didn't want to use Django's in-build authentication system (maybe I should do, please tell me if this is the case), I created a simple little auth class:

import random
import hashlib
from myapp import models

class CustomerAuth:
    key = 'customer'

    def __init__(self, session):
        self.session = session

    def attempt(self, email_address, password):
        password_hash = hashlib.sha1(password).hexdigest()
        try:
            return models.Customer.objects.get(
                email_address=email_address,
                password_hash=password_hash)
        except models.Customer.DoesNotExist:
            return None

    def login(self, customer):
        self.session[self.key] = customer

    def logout(self):
        if self.session.has_key(self.key):
            self.session[self.key] = None

    def is_logged_in(self):
        return self.session.has_key(self.key)
            and self.session[self.key] != None

    def get_active(self):
        if self.is_logged_in():
            return self.session[self.key]
        else:
            raise Exception('No user is logged in.')

    def redirect_to_login(self):
        return HttpResponseRedirect('/login/')

    def redirect_from_login(self):
        return HttpResponseRedirect('/account/')

The problem is, that when I want to use it to stop unauthorized access, I have to use this code snippet in every single view method:

def example(req):
    auth = CustomerAuth(req.session)
    if not auth.is_logged_in():
        return auth.redirect_to_login()

As you can imagine, this yields fairly ugly and repetitive code. What is a better way of doing this? Should I be using Django's auth framework?

+4  A: 

Firstly, yes you should use Django's authentication framework, and build your own custom auth backend.

Secondly, however you do it, you'll need to have something in the views that you want to restrict access to. The best way to do that is via a decorator on the view. Again, Django's built-in framework gives you access to the @login_required decorator, which does exactly what you want.

Daniel Roseman
Thanks - just implemented it now. It's actually very easy to do surprisingly. Plus, I don't need to use the username attribute even through it's "required" (since I want to do authentication with email addresses).
nbolton