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