views:

87

answers:

4

Hay I was wondering if anyone knew a better way to do this.

def login_user(request):
    username = request.POST.get('username')
    password = request.POST.get('password')

    user = User.objects.filter(username=username)

    if user:
        user = user[0]
        if user.password == generate_password(password):
            return HttpResponse("password fine")
        else:
            return HttpResponse("password incorrect")
    else:
        return HttpResponse("no user found by that username")

and the generate_password function is just

generate_password(string):
    return hashlib.sha224(str(string)).hexdigest()

Any ideas would be great.

Thanks

+4  A: 

Why don't use Django auth default views ?

Ghislain Leveque
Prefer to write my own to aid my python learning. I know people say 'don't reinvent the wheel', but i find reinventing it helps a lot when learning!
dotty
This is a wheel you should not be reinventing - at best you will put a lot of effort into something that had already been implemented; at worst you'll waste effort and get it wrong. Why don't you use your time to come up with an awesome Internet site? Solve real problems, not imaginary ones.
Arrieta
If you want to learn Python better, read the existing contrib.auth code. It's fine to do this for edification, just not for production code.http://code.djangoproject.com/browser/django/trunk/django/contrib/auth
Adam Nelson
In general I agree with the 'do not reinvent the wheel' principle. That said I worked on a project where it was necessary to record login and logout events in an application log. Since `auth` does not emit any signals or provide any hooks to do this I had to come up with my own mechanism to go about this. There is a ticket open for this: http://code.djangoproject.com/ticket/5612
Manoj Govindan
+1  A: 

the only amelioration i see is use get instead of filter (it will save you one line)

user = User.objects.get(username=username)
Mermoz
If you do this, remember that you need to catch a `User.DoesNotExist exception` instead of checking `if user`
Alasdair
@Mermoz, can you give an example of how to implement it.
dotty
+1  A: 

Looking at the level of control you want to have, you'll want to make use of the authenticate and maybe login functions in django.contrib.auth. These are the main functions for accessing authentication. I should stress that you really, really should use these instead of finding the user and checking the password hash manually. There are a number of reasons why:

  • they will make use of whatever authentication backend you or someone else in the future have installed
  • your version will be far less tested than Django's and is more likely to open security holes
  • it's quicker, shorter, more flexible and more readable
  • Django's auth app will probably change in the near future, sticking to authenticate will help you migrate to the new auth app when it gets written/committed/released

If you do want to rewrite the way a user is found and authenticated, write your own Authenticate backend, which will be used when you call authentication (even in someone else's app, like the admin). This is the only place you should rewrite authentication in Django.

The following examples are from the Django auth docs.

1. Checking a user's password:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    if user.is_active:
        print "You provided a correct username and password!"
    else:
        print "Your account has been disabled!"
else:
    print "Your username and password were incorrect."

2. Custom authentication backend:

Here is a backend that uses the same authenticate method as Django's, which you can find at django.contrib.auth.backends.ModelBackend:

from django.contrib.auth.models import User

class MyBackend:
  def authenticate(self, username=None, password=None):
    try:
      user = User.objects.get(username=username)
      if user.check_password(password):
        return user
    except User.DoesNotExist:
      return None

  def get_user(self, user_id):
    try:
      return User.objects.get(pk=user_id)
    except User.DoesNotExist:
      return None
Will Hardy
Thanks for this, I'd really prefer to use my own system. Can you see any obvious security holes in my code?
dotty
Above is exactly how you would do it. If you want to rewrite the way a user is authenticated, write your own authentication backend. If you do that, Django will use your custom `authenticate` function: http://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backendIt's good design practice to separate the logic of authenticating a user into a separate module/function. Django encourages this by providing the `authenticate` function and allowing you to override its implementation. Please don't do it any other way with Django!
Will Hardy
Not sure about security holes, but: 1) There's an uncaught `KeyError` if `password` or `username` are not passed as GET parameters. 2) An encoding error if password has a character which can't be converted to ascii in `generate_password` 3) you're not taking inactive accounts into consideration 4) I'm not even sure it would work, given that django passwords are stored " *algorithm* `$` *salt* `$` *hash* " 5) any custom backend authentication is ignored.
Will Hardy
A: 

You should download django-registration and go through the code. It manages everything for you, including cleaning the code. Your original code will not handle empty submissions.

http://bitbucket.org/ubernostrum/django-registration/

Ali