- Timestamp:
- 29 Nov 2018, 16:24:00 (6 years ago)
- Location:
- main/waeup.ikoba/trunk/src/waeup/ikoba/browser
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.ikoba/trunk/src/waeup/ikoba/browser/captcha.py
r11954 r15256 21 21 """ 22 22 import grok 23 import json 23 24 import urllib 24 25 import urllib2 … … 163 164 164 165 ## 165 ## ReCaptcha 166 ## 167 API_SSL_SERVER = "https://www.google.com/recaptcha/api" 168 VERIFY_SERVER = "https://www.google.com/recaptcha/api" 166 ## ReCaptcha (v2) 167 ## 169 168 170 169 class ReCaptcha(StaticCaptcha): … … 172 171 173 172 This is the Ikoba implementation to support captchas as provided by 174 http://www.google.com/recaptcha .173 http://www.google.com/recaptcha (v2). 175 174 176 175 ReCaptcha is widely used and adopted in web applications. See the … … 220 219 This captcha is available at runtime as a global utility named 221 220 ``'ReCaptcha'``. 221 222 Shortcomings: 223 - no support for selecting theme 224 - no support for selecting box layout (normal, compact) 225 - no support for non-javascript users 226 - Google will get the data of our clients 227 - Google will track all activity of our clients 222 228 """ 223 229 224 230 grok.implements(ICaptcha) 225 231 226 #: name of solution field in HTTP request 227 sol_field = 'recaptcha_response_field' 228 #: name of challenge field in HTTP request 229 chal_field = 'recaptcha_challenge_field' 232 #: name of response token field in HTTP request 233 token_field = 'g-recaptcha-response' 230 234 231 235 # Do not use the following keys in productive environments! As … … 235 239 PRIVATE_KEY = "6Lc0y8oSAAAAAMHVbMrGWLLjw2pm8v2Uprwm9AbR" 236 240 241 VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify' 242 237 243 def verify(self, request): 238 244 """Grab challenge/solution from HTTP request and verify it. 239 245 240 246 Verification happens against recaptcha remote API servers. It 241 only happens, when really a solution was sent with the247 only happens, when a repsonse token was sent with the 242 248 request. 243 249 … … 246 252 """ 247 253 form = getattr(request, 'form', {}) 248 solution=form.get(self.sol_field, None) 249 challenge=form.get(self.chal_field, None) 250 if not challenge or not solution: 251 # Might be first-time display of the captcha: not a valid 252 # solution but no error code to prevent any error 253 # messages. Skip further verification. 254 return CaptchaResponse( 255 is_valid=False) 254 token = form.get(self.token_field, None) 255 if not token: 256 # on first-time display, we won't get a token 257 return CaptchaResponse(is_valid=False) 256 258 params = urllib.urlencode( 257 259 { 258 'privatekey': self.PRIVATE_KEY, 260 'secret': self.PRIVATE_KEY, 261 'response': token, 259 262 'remoteip': '127.0.0.1', 260 'challenge': challenge,261 'response': solution,262 263 }) 263 264 request = urllib2.Request( 264 url = "%s/verify" % VERIFY_SERVER,265 url = self.VERIFY_URL, 265 266 data = params, 266 267 headers = { 267 268 "Content-type": "application/x-www-form-urlencoded", 268 "User-agent": "reCAPTCHA Python Ikoba",269 "User-agent": "reCAPTCHA Python Kofa", 269 270 } 270 271 ) 271 resp = urllib2.urlopen(request) 272 ret_vals = resp.read().splitlines() 273 resp.close() 274 ret_code, err_code = ret_vals 275 276 if ret_code == "true": 272 conn = urllib2.urlopen(request) 273 ret_vals = json.loads(conn.read()) 274 conn.close() 275 if ret_vals.get('success', False) is True: 277 276 return CaptchaResponse(is_valid=True) 278 return CaptchaResponse(is_valid=False, error_code=ret_vals[1]) 277 return CaptchaResponse( 278 is_valid=False, error_code="%s" % ret_vals['error-codes']) 279 279 280 280 def display(self, error_code=None): 281 """Display c hallenge and input field for solution as HTML.281 """Display captcha widget snippet. 282 282 283 283 Returns the HTML code to be placed inside an existing ``<form>`` … … 297 297 html = ( 298 298 u'<script type="text/javascript" ' 299 u'src="%(ApiServer)s /challenge?k=%(PublicKey)s%(ErrorParam)s">'299 u'src="%(ApiServer)s" async defer>' 300 300 u'</script>' 301 u'' 302 u'<noscript>' 303 u'<iframe' 304 u' src="%(ApiServer)s/noscript?k=%(PublicKey)s%(ErrorParam)s"' 305 u' height="300" width="500" frameborder="0"></iframe><br />' 306 u'<textarea name="recaptcha_challenge_field"' 307 u' rows="3" cols="40"></textarea>' 308 u'<input type="hidden" name="recaptcha_response_field"' 309 u' value="manual_challenge" />' 310 u'</noscript>' % { 311 'ApiServer' : API_SSL_SERVER, 312 'PublicKey' : self.PUBLIC_KEY, 313 'ErrorParam' : error_param, 301 u'<div class="g-recaptcha" data-sitekey="%(SiteKey)s"></div>' % { 302 'ApiServer': "https://www.google.com/recaptcha/api.js", 303 'SiteKey': self.PUBLIC_KEY, 314 304 } 315 305 ) 316 306 return html 307 317 308 318 309 grok.global_utility(ReCaptcha, name=u'ReCaptcha') -
main/waeup.ikoba/trunk/src/waeup/ikoba/browser/tests/test_captcha.py
r11949 r15256 171 171 result = captcha.display() 172 172 self.assertMatches( 173 '<script type="text/javascript" src="..."></script>' 174 '<noscript>' 175 '<iframe src="..." height="300" width="500" ' 176 ' frameborder="0"></iframe><br />' 177 '<textarea name="recaptcha_challenge_field" rows="3" ' 178 ' cols="40"></textarea>' 179 '<input type="hidden" name="recaptcha_response_field" ' 180 ' value="manual_challenge" /></noscript>', 173 '<script type="text/javascript" ' 174 'src="..." async defer></script>' 175 '<div class="g-recaptcha" data-sitekey="..."></div>', 181 176 result) 182 177 return
Note: See TracChangeset for help on using the changeset viewer.