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 | from django.http import HttpResponse
from piston.authentication import OAuthAuthentication, HttpBasicAuthentication
class MultiValueHttpResponse(HttpResponse):
'''
A subclass of HttpResponse that is capable of representing multiple instances of a header.
Use 'add_header_value' to set or add a value for a header.
Use 'get_header_values' to get all values for a header.
'items' returns an array containing each value for each header.
'get' and '__getitem__' return the first value for the requested header.
'__setitem__' replaces all values for a header with the provided value.
'''
def __init__(self, *args, **kwargs):
super(MultiValueHttpResponse, self).__init__(*args, **kwargs)
self._multi_value_headers = {}
# the constructor may set some headers already
for item in super(MultiValueHttpResponse, self).items():
self[item[0]] = item[1]
def __str__(self):
return '\n'.join(['%s: %s' % (key, value)
for key, value in self.items()]) + '\n\n' + self.content
def __setitem__(self, header, value):
header, value = self._convert_to_ascii(header, value)
self._multi_value_headers[header.lower()] = [(header, value)]
def __getitem__(self, header):
return self._multi_value_headers[header.lower()][0][1]
def items(self):
items = []
for header_values in self._multi_value_headers.values():
for entry in header_values:
items.append((entry[0], entry[1]))
return items
def get(self, header, alternate):
return self._multi_value_headers.get(header.lower(), [(None, alternate)])[0][1]
def add_header_value(self, header, value):
header, value = self._convert_to_ascii(header, value)
lower_header = header.lower()
if not lower_header in self._multi_value_headers:
self._multi_value_headers[lower_header] = []
self._multi_value_headers[lower_header].append((header, value))
def get_header_values(self, header):
header = self._convert_to_ascii(header)
return [header[1] for header in self._multi_value_headers.get(header.lower(), [])]
class MultipleAuthentication(object):
def __init__(self, **methods):
self.methods = methods
def is_authenticated(self, request):
auth_header = request.META.get('HTTP_AUTHORIZATION', None)
if not auth_header:
return False
(method, auth) = auth_header.split(" ", 1)
if method in self.methods:
return self.methods[method].is_authenticated(request)
return False
def challenge(self):
response = MultiValueHttpResponse('Authorization Required',
content_type="text/plain", status=401)
for method in self.methods.values():
challenge = method.challenge().get('WWW-Authenticate', None)
if challenge:
response.add_header_value('WWW-Authenticate', challenge)
return response
API_AUTHENTICATION = MultipleAuthentication(Basic=HttpBasicAuthentication(),
OAuth=OAuthAuthentication())
|
Comments