Login

Basic HTTP Authentication

Author:
pterk
Posted:
February 28, 2007
Language:
Python
Version:
Pre .96
Score:
-1 (after 1 ratings)

A patch (against django svn trunk 4649) that allows users to log in with Basic HTTP Authentication i.s.o. login forms using some simple middleware (entire patch is ~50 lines). I was unaware of http://code.djangoproject.com/wiki/GenericAuthorization so I'm not sure about its usefulness in the long run.

You can enable it by including 'django.contrib.auth.middleware.BasicAuthenticationMiddleware' in your MIDDLEWARE_CLASSES and then adding the following lines in your settings.py:

BASIC_WWW_AUTHENTICATION = True

WWW_AUTHENTICATION_REALM = "djangolures.com"

Updated: See also http://code.djangoproject.com/ticket/3609 (patch now availble here as well).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
Index: django/contrib/admin/views/decorators.py
===================================================================
--- django/contrib/admin/views/decorators.py    (revision 4649)
+++ django/contrib/admin/views/decorators.py    (working copy)
@@ -2,6 +2,7 @@
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.auth import authenticate, login
+from django.contrib.auth.middleware import basic_challenge
 from django.shortcuts import render_to_response
 from django.utils.translation import gettext_lazy
 import base64, datetime, md5
@@ -11,6 +12,8 @@
 LOGIN_FORM_KEY = 'this_is_the_login_form'

 def _display_login_form(request, error_message=''):
+    if getattr(settings, 'BASIC_WWW_AUTHENTICATION', False):
+        return basic_challenge()
     request.session.set_test_cookie()
     if request.POST and request.POST.has_key('post_data'):
         # User has failed login BUT has previously saved post data.
Index: django/contrib/auth/middleware.py
===================================================================
--- django/contrib/auth/middleware.py   (revision 4649)
+++ django/contrib/auth/middleware.py   (working copy)
@@ -1,3 +1,40 @@
+from django.conf import settings
+from django.http import HttpResponse
+
+from django.contrib.auth import authenticate, login, logout
+
+def basic_challenge(realm = None):
+    if realm is None:
+        realm = getattr(settings, 'WWW_AUTHENTICATION_REALM', _('Restricted Access'))
+    # TODO: Make a nice template for a 401 message?
+    response =  HttpResponse(_('Authorization Required'), mimetype="text/plain")
+    response['WWW-Authenticate'] = 'Basic realm="%s"' % (realm)
+    response.status_code = 401
+    return response
+
+def basic_authenticate(authentication):
+    # Taken from paste.auth
+    (authmeth, auth) = authentication.split(' ',1)
+    if 'basic' != authmeth.lower():
+        return None
+    auth = auth.strip().decode('base64')
+    username, password = auth.split(':',1)
+    return authenticate(username = username, password = password)
+
+class BasicAuthenticationMiddleware:
+    def process_request(self, request):
+        if not getattr(settings, 'BASIC_WWW_AUTHENTICATION', False):
+            return None
+        if not request.META.has_key('HTTP_AUTHORIZATION'):
+            # If the user out of the session as well
+            logout(request)
+            return None
+        user =  basic_authenticate(request.META['HTTP_AUTHORIZATION'])
+        if user is None:
+            return basic_challenge()
+        else:
+            login(request, user)
+
 class LazyUser(object):
     def __get__(self, request, obj_type=None):
         if not hasattr(request, '_cached_user'):
Index: django/contrib/auth/views.py
===================================================================
--- django/contrib/auth/views.py        (revision 4649)
+++ django/contrib/auth/views.py        (working copy)
@@ -35,6 +35,12 @@
     "Logs out the user and displays 'You are logged out' message."
     from django.contrib.auth import logout
     logout(request)
+
+    # This 'works' as a way to log out users but it is confusing. You
+    # log out and it asks for your credentials again?
+    #if not getattr(settings, 'BASIC_WWW_AUTHENTICATION', False):
+    #    from middleware import basic_challenge
+    #    return basic_challenge()
     if next_page is None:
         return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request))
     else:
Index: django/contrib/auth/decorators.py
===================================================================
--- django/contrib/auth/decorators.py   (revision 4649)
+++ django/contrib/auth/decorators.py   (working copy)
@@ -1,3 +1,5 @@
+from django.conf import settings
+
 from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
 from django.http import HttpResponseRedirect
 from urllib import quote
@@ -2,2 +4,4 @@

+from django.contrib.auth.middleware import basic_challenge
+
 def user_passes_test(test_func, login_url=LOGIN_URL):
@@ -12,10 +16,12 @@
         def _checklogin(request, *args, **kwargs):
             if test_func(request.user):
                 return view_func(request, *args, **kwargs)
-            return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
+            if getattr(settings, 'BASIC_WWW_AUTHENTICATION', False):
+                return basic_challenge()
+            else:
+                return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
         _checklogin.__doc__ = view_func.__doc__
         _checklogin.__dict__ = view_func.__dict__
-
         return _checklogin
     return _dec

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

Please login first before commenting.