1 import base64
2
3 from django.http import HttpResponse
4 from django.contrib.auth import authenticate, login
5
6
7
9 """
10 This is a helper function used by both 'logged_in_or_basicauth' and
11 'has_perm_or_basicauth' that does the nitty of determining if they
12 are already logged in or if they have provided proper http-authorization
13 and returning the view if all goes well, otherwise responding with a 401.
14 """
15 if test_func(request.user):
16
17
18 return view(request, *args, **kwargs)
19
20
21
22 if 'HTTP_AUTHORIZATION' in request.META:
23 auth = request.META['HTTP_AUTHORIZATION'].split()
24 if len(auth) == 2:
25
26
27 if auth[0].lower() == "basic":
28 uname, passwd = base64.b64decode(auth[1]).split(':')
29 user = authenticate(username=uname, password=passwd)
30 if user is not None:
31 if user.is_active:
32 login(request, user)
33 request.user = user
34 return view(request, *args, **kwargs)
35
36
37
38
39
40 response = HttpResponse()
41 response.status_code = 401
42 response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
43 return response
44
45
46
48 """
49 A simple decorator that requires a user to be logged in. If they are not
50 logged in the request is examined for a 'authorization' header.
51
52 If the header is present it is tested for basic authentication and
53 the user is logged in with the provided credentials.
54
55 If the header is not present a http 401 is sent back to the
56 requestor to provide credentials.
57
58 The purpose of this is that in several django projects I have needed
59 several specific views that need to support basic authentication, yet the
60 web site as a whole used django's provided authentication.
61
62 The uses for this are for urls that are access programmatically such as
63 by rss feed readers, yet the view requires a user to be logged in. Many rss
64 readers support supplying the authentication credentials via http basic
65 auth (and they do NOT support a redirect to a form where they post a
66 username/password.)
67
68 Use is simple:
69
70 @logged_in_or_basicauth
71 def your_view:
72 ...
73
74 You can provide the name of the realm to ask for authentication within.
75 """
76 def view_decorator(func):
77 def wrapper(request, *args, **kwargs):
78 return view_or_basicauth(func, request,
79 lambda u: u.is_authenticated(),
80 realm, *args, **kwargs)
81 return wrapper
82 return view_decorator
83
84
85
87 """
88 This is similar to the above decorator 'logged_in_or_basicauth'
89 except that it requires the logged in user to have a specific
90 permission.
91
92 Use:
93
94 @logged_in_or_basicauth('asforums.view_forumcollection')
95 def your_view:
96 ...
97
98 """
99 def view_decorator(func):
100 def wrapper(request, *args, **kwargs):
101 return view_or_basicauth(func, request,
102 lambda u: u.has_perm(perm),
103 realm, *args, **kwargs)
104 return wrapper
105 return view_decorator
106