Guest User

Untitled

a guest
Jul 18th, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.31 KB | None | 0 0
  1. ## urls.py
  2. from contracts import models
  3. from rest.django_restapi.model_resource import Collection
  4. from rest.django_restapi.responder import XMLResponder
  5. from django.conf.urls.defaults import *
  6. from rest.django_restapi.authentication import *
  7.  
  8. contract_resource = Collection(
  9. queryset = models.Contract.objects.all(),
  10. permitted_methods = ('GET', 'POST', 'PUT', 'DELETE'),
  11. responder = XMLResponder(paginate_by = 10),
  12. authentication = HttpBasicAuthentication()
  13. )
  14.  
  15. product_resource = Collection(
  16. queryset = models.Product.objects.all(),
  17. permitted_methods = ('GET', 'POST', 'PUT', 'DELETE'),
  18. responder = XMLResponder(paginate_by = 10)
  19. )
  20.  
  21. urlpatterns = patterns('contracts.views',
  22. url(r'^xml/contract/(.*?)/?$', contract_resource),
  23. url(r'^xml/product/(.*?)/?$', product_resource),
  24. )
  25.  
  26.  
  27. ## authentication.py
  28.  
  29. from django.http import HttpResponse
  30. from django.utils.translation import ugettext as _
  31. import md5, time, random
  32.  
  33. def djangouser_auth(username, password):
  34. """
  35. Check username and password against
  36. django.contrib.auth.models.User
  37. """
  38. from django.contrib.auth.models import User
  39. try:
  40. user = User.objects.get(username=username)
  41. if user.check_password(password):
  42. return True
  43. else:
  44. return False
  45. except User.DoesNotExist:
  46. return False
  47.  
  48. class NoAuthentication(object):
  49. """
  50. No authentication: Permit every request.
  51. """
  52. def is_authenticated(self, request):
  53. return True
  54.  
  55. def challenge_headers(self):
  56. return {}
  57.  
  58. class HttpBasicAuthentication(object):
  59. """
  60. HTTP/1.0 basic authentication.
  61. """
  62. def __init__(self, authfunc=djangouser_auth, realm=_('Restricted Access')):
  63. """
  64. authfunc:
  65. A user-defined function which takes a username and
  66. password as its first and second arguments respectively
  67. and returns True if the user is authenticated
  68. realm:
  69. An identifier for the authority that is requesting
  70. authorization
  71. """
  72. self.realm = realm
  73. self.authfunc = authfunc
  74.  
  75. def challenge_headers(self):
  76. """
  77. Returns the http headers that ask for appropriate
  78. authorization.
  79. """
  80. return {'WWW-Authenticate' : 'Basic realm="%s"' % self.realm}
  81.  
  82. def is_authenticated(self, request):
  83. """
  84. Checks whether a request comes from an authorized user.
  85. """
  86. if not request.META.has_key('HTTP_AUTHORIZATION'):
  87. return False
  88. (authmeth, auth) = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
  89. if authmeth.lower() != 'basic':
  90. return False
  91. auth = auth.strip().decode('base64')
  92. username, password = auth.split(':', 1)
  93. return self.authfunc(username=username, password=password)
  94.  
  95. def digest_password(realm, username, password):
  96. """
  97. Construct the appropriate hashcode needed for HTTP digest
  98. """
  99. return md5.md5("%s:%s:%s" % (username, realm, password)).hexdigest()
  100.  
  101. class HttpDigestAuthentication(object):
  102. """
  103. HTTP/1.1 digest authentication (RFC 2617).
  104. Uses code from the Python Paste Project (MIT Licence).
  105. """
  106. def __init__(self, authfunc, realm=_('Restricted Access')):
  107. """
  108. authfunc:
  109. A user-defined function which takes a username and
  110. a realm as its first and second arguments respectively
  111. and returns the combined md5 hash of username,
  112. authentication realm and password.
  113. realm:
  114. An identifier for the authority that is requesting
  115. authorization
  116. """
  117. self.realm = realm
  118. self.authfunc = authfunc
  119. self.nonce = {} # prevention of replay attacks
  120.  
  121. def get_auth_dict(self, auth_string):
  122. """
  123. Splits WWW-Authenticate and HTTP_AUTHORIZATION strings
  124. into a dictionaries, e.g.
  125. {
  126. nonce : "951abe58eddbb49c1ed77a3a5fb5fc2e"',
  127. opaque : "34de40e4f2e4f4eda2a3952fd2abab16"',
  128. realm : "realm1"',
  129. qop : "auth"'
  130. }
  131. """
  132. amap = {}
  133. for itm in auth_string.split(", "):
  134. (k, v) = [s.strip() for s in itm.split("=", 1)]
  135. amap[k] = v.replace('"', '')
  136. return amap
  137.  
  138. def get_auth_response(self, http_method, fullpath, username, nonce, realm, qop, cnonce, nc):
  139. """
  140. Returns the server-computed digest response key.
  141.  
  142. http_method:
  143. The request method, e.g. GET
  144. username:
  145. The user to be authenticated
  146. fullpath:
  147. The absolute URI to be accessed by the user
  148. nonce:
  149. A server-specified data string which should be
  150. uniquely generated each time a 401 response is made
  151. realm:
  152. A string to be displayed to users so they know which
  153. username and password to use
  154. qop:
  155. Indicates the "quality of protection" values supported
  156. by the server. The value "auth" indicates authentication.
  157. cnonce:
  158. An opaque quoted string value provided by the client
  159. and used by both client and server to avoid chosen
  160. plaintext attacks, to provide mutual authentication,
  161. and to provide some message integrity protection.
  162. nc:
  163. Hexadecimal request counter
  164. """
  165. ha1 = self.authfunc(realm, username)
  166. ha2 = md5.md5('%s:%s' % (http_method, fullpath)).hexdigest()
  167. if qop:
  168. chk = "%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2)
  169. else:
  170. chk = "%s:%s:%s" % (ha1, nonce, ha2)
  171. computed_response = md5.md5(chk).hexdigest()
  172. return computed_response
  173.  
  174. def challenge_headers(self, stale=''):
  175. """
  176. Returns the http headers that ask for appropriate
  177. authorization.
  178. """
  179. nonce = md5.md5(
  180. "%s:%s" % (time.time(), random.random())).hexdigest()
  181. opaque = md5.md5(
  182. "%s:%s" % (time.time(), random.random())).hexdigest()
  183. self.nonce[nonce] = None
  184. parts = {'realm': self.realm, 'qop': 'auth',
  185. 'nonce': nonce, 'opaque': opaque }
  186. if stale:
  187. parts['stale'] = 'true'
  188. head = ", ".join(['%s="%s"' % (k, v) for (k, v) in parts.items()])
  189. return {'WWW-Authenticate':'Digest %s' % head}
  190.  
  191. def is_authenticated(self, request):
  192. """
  193. Checks whether a request comes from an authorized user.
  194. """
  195.  
  196. # Make sure the request is a valid HttpDigest request
  197. if not request.META.has_key('HTTP_AUTHORIZATION'):
  198. return False
  199. fullpath = request.META['SCRIPT_NAME'] + request.META['PATH_INFO']
  200. (authmeth, auth) = request.META['HTTP_AUTHORIZATION'].split(" ", 1)
  201. if authmeth.lower() != 'digest':
  202. return False
  203.  
  204. # Extract auth parameters from request
  205. amap = self.get_auth_dict(auth)
  206. try:
  207. username = amap['username']
  208. authpath = amap['uri']
  209. nonce = amap['nonce']
  210. realm = amap['realm']
  211. response = amap['response']
  212. assert authpath.split("?", 1)[0] in fullpath
  213. assert realm == self.realm
  214. qop = amap.get('qop', '')
  215. cnonce = amap.get('cnonce', '')
  216. nc = amap.get('nc', '00000000')
  217. if qop:
  218. assert 'auth' == qop
  219. assert nonce and nc
  220. except:
  221. return False
  222.  
  223. # Compute response key
  224. computed_response = self.get_auth_response(request.method, fullpath, username, nonce, realm, qop, cnonce, nc)
  225.  
  226. # Compare server-side key with key from client
  227. # Prevent replay attacks
  228. if not computed_response or computed_response != response:
  229. if nonce in self.nonce:
  230. del self.nonce[nonce]
  231. return False
  232. pnc = self.nonce.get(nonce,'00000000')
  233. if nc <= pnc:
  234. if nonce in self.nonce:
  235. del self.nonce[nonce]
  236. return False # stale = True
  237. self.nonce[nonce] = nc
  238. return True
Add Comment
Please, Sign In to add comment