1 #############################################################################
2 # from http://djangosnippets.org/snippets/243/
4 from functools import wraps
7 from django.http import HttpResponse
8 from django.contrib.auth import authenticate, login
11 def view_or_basicauth(view, request, test_func, realm="", *args, **kwargs):
13 This is a helper function used by 'logged_in_or_basicauth' and
14 'has_perm_or_basicauth' (deleted) that does the nitty of determining if they
15 are already logged in or if they have provided proper http-authorization
16 and returning the view if all goes well, otherwise responding with a 401.
18 if test_func(request.user):
19 # Already logged in, just return the view.
21 return view(request, *args, **kwargs)
23 # They are not logged in. See if they provided login credentials
25 if 'HTTP_AUTHORIZATION' in request.META:
26 auth = request.META['HTTP_AUTHORIZATION'].split()
28 # NOTE: We are only support basic authentication for now.
30 if auth[0].lower() == "basic":
31 uname, passwd = base64.b64decode(auth[1].encode('utf-8')).decode('utf-8').split(':')
32 user = authenticate(username=uname, password=passwd)
37 return view(request, *args, **kwargs)
39 # Either they did not provide an authorization header or
40 # something in the authorization attempt failed. Send a 401
41 # back to them to ask them to authenticate.
43 response = HttpResponse()
44 response.status_code = 401
45 response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
50 def logged_in_or_basicauth(realm=""):
52 A simple decorator that requires a user to be logged in. If they are not
53 logged in the request is examined for a 'authorization' header.
55 If the header is present it is tested for basic authentication and
56 the user is logged in with the provided credentials.
58 If the header is not present a http 401 is sent back to the
59 requestor to provide credentials.
61 The purpose of this is that in several django projects I have needed
62 several specific views that need to support basic authentication, yet the
63 web site as a whole used django's provided authentication.
65 The uses for this are for urls that are access programmatically such as
66 by rss feed readers, yet the view requires a user to be logged in. Many rss
67 readers support supplying the authentication credentials via http basic
68 auth (and they do NOT support a redirect to a form where they post a
73 @logged_in_or_basicauth
77 You can provide the name of the realm to ask for authentication within.
79 def view_decorator(func):
80 def wrapper(request, *args, **kwargs):
81 return view_or_basicauth(func, request,
82 lambda u: u.is_authenticated(),
83 realm, *args, **kwargs)
88 #############################################################################
91 def factory_decorator(decorator):
92 """ generates a decorator for a function factory class
93 if A(*) == f, factory_decorator(D)(A)(*) == D(f)
97 def wrapper(*args, **kwargs):
98 return decorator(func(*args, **kwargs))