Package cherrypy :: Package test :: Module test_httpauth
[hide private]
[frames] | no frames]

Source Code for Module cherrypy.test.test_httpauth

  1  import cherrypy 
  2  from cherrypy._cpcompat import md5, sha, ntob 
  3  from cherrypy.lib import httpauth 
  4   
  5  from cherrypy.test import helper 
  6   
7 -class HTTPAuthTest(helper.CPWebCase):
8
9 - def setup_server():
10 class Root: 11 def index(self): 12 return "This is public."
13 index.exposed = True
14 15 class DigestProtected: 16 def index(self): 17 return "Hello %s, you've been authorized." % cherrypy.request.login 18 index.exposed = True 19 20 class BasicProtected: 21 def index(self): 22 return "Hello %s, you've been authorized." % cherrypy.request.login 23 index.exposed = True 24 25 class BasicProtected2: 26 def index(self): 27 return "Hello %s, you've been authorized." % cherrypy.request.login 28 index.exposed = True 29 30 def fetch_users(): 31 return {'test': 'test'} 32 33 def sha_password_encrypter(password): 34 return sha(ntob(password)).hexdigest() 35 36 def fetch_password(username): 37 return sha(ntob('test')).hexdigest() 38 39 conf = {'/digest': {'tools.digest_auth.on': True, 40 'tools.digest_auth.realm': 'localhost', 41 'tools.digest_auth.users': fetch_users}, 42 '/basic': {'tools.basic_auth.on': True, 43 'tools.basic_auth.realm': 'localhost', 44 'tools.basic_auth.users': {'test': md5(ntob('test')).hexdigest()}}, 45 '/basic2': {'tools.basic_auth.on': True, 46 'tools.basic_auth.realm': 'localhost', 47 'tools.basic_auth.users': fetch_password, 48 'tools.basic_auth.encrypt': sha_password_encrypter}} 49 50 root = Root() 51 root.digest = DigestProtected() 52 root.basic = BasicProtected() 53 root.basic2 = BasicProtected2() 54 cherrypy.tree.mount(root, config=conf) 55 setup_server = staticmethod(setup_server) 56 57
58 - def testPublic(self):
59 self.getPage("/") 60 self.assertStatus('200 OK') 61 self.assertHeader('Content-Type', 'text/html;charset=utf-8') 62 self.assertBody('This is public.')
63
64 - def testBasic(self):
65 self.getPage("/basic/") 66 self.assertStatus(401) 67 self.assertHeader('WWW-Authenticate', 'Basic realm="localhost"') 68 69 self.getPage('/basic/', [('Authorization', 'Basic dGVzdDp0ZX60')]) 70 self.assertStatus(401) 71 72 self.getPage('/basic/', [('Authorization', 'Basic dGVzdDp0ZXN0')]) 73 self.assertStatus('200 OK') 74 self.assertBody("Hello test, you've been authorized.")
75
76 - def testBasic2(self):
77 self.getPage("/basic2/") 78 self.assertStatus(401) 79 self.assertHeader('WWW-Authenticate', 'Basic realm="localhost"') 80 81 self.getPage('/basic2/', [('Authorization', 'Basic dGVzdDp0ZX60')]) 82 self.assertStatus(401) 83 84 self.getPage('/basic2/', [('Authorization', 'Basic dGVzdDp0ZXN0')]) 85 self.assertStatus('200 OK') 86 self.assertBody("Hello test, you've been authorized.")
87
88 - def testDigest(self):
89 self.getPage("/digest/") 90 self.assertStatus(401) 91 92 value = None 93 for k, v in self.headers: 94 if k.lower() == "www-authenticate": 95 if v.startswith("Digest"): 96 value = v 97 break 98 99 if value is None: 100 self._handlewebError("Digest authentification scheme was not found") 101 102 value = value[7:] 103 items = value.split(', ') 104 tokens = {} 105 for item in items: 106 key, value = item.split('=') 107 tokens[key.lower()] = value 108 109 missing_msg = "%s is missing" 110 bad_value_msg = "'%s' was expecting '%s' but found '%s'" 111 nonce = None 112 if 'realm' not in tokens: 113 self._handlewebError(missing_msg % 'realm') 114 elif tokens['realm'] != '"localhost"': 115 self._handlewebError(bad_value_msg % ('realm', '"localhost"', tokens['realm'])) 116 if 'nonce' not in tokens: 117 self._handlewebError(missing_msg % 'nonce') 118 else: 119 nonce = tokens['nonce'].strip('"') 120 if 'algorithm' not in tokens: 121 self._handlewebError(missing_msg % 'algorithm') 122 elif tokens['algorithm'] != '"MD5"': 123 self._handlewebError(bad_value_msg % ('algorithm', '"MD5"', tokens['algorithm'])) 124 if 'qop' not in tokens: 125 self._handlewebError(missing_msg % 'qop') 126 elif tokens['qop'] != '"auth"': 127 self._handlewebError(bad_value_msg % ('qop', '"auth"', tokens['qop'])) 128 129 # Test a wrong 'realm' value 130 base_auth = 'Digest username="test", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' 131 132 auth = base_auth % (nonce, '', '00000001') 133 params = httpauth.parseAuthorization(auth) 134 response = httpauth._computeDigestResponse(params, 'test') 135 136 auth = base_auth % (nonce, response, '00000001') 137 self.getPage('/digest/', [('Authorization', auth)]) 138 self.assertStatus(401) 139 140 # Test that must pass 141 base_auth = 'Digest username="test", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' 142 143 auth = base_auth % (nonce, '', '00000001') 144 params = httpauth.parseAuthorization(auth) 145 response = httpauth._computeDigestResponse(params, 'test') 146 147 auth = base_auth % (nonce, response, '00000001') 148 self.getPage('/digest/', [('Authorization', auth)]) 149 self.assertStatus('200 OK') 150 self.assertBody("Hello test, you've been authorized.")
151