An Alternative to Image based CAPTCHA – the code
as promised below, here is a sample class to use for my version of CAPTCHA
<? class nonce{ public function deliverJS(){ if (!empty($GLOBALS['JSDelivered'])) { //return ''; } $js = <<<JS <script type="text/javascript"> var xo = false; var t; function createObject(){ if(window.XMLHttpRequest && !(window.ActiveXObject)) { try { xo = new XMLHttpRequest(); } catch(e) { xo = false; } // branch for IE/Windows ActiveX version } else if(window.ActiveXObject) { try { xo = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xo = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xo = false; } } } } function getNonce(fld){ while (!xo){ createObject(); } xo.onreadystatechange = function(){ if (xo.readyState == 4) { if (xo.status == 200) { fld.value = xo.responseText; } } } xo.open("POST", "nonce.php", true); xo.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded;'); xo.send("action=getNonce&type=form"); } function populateNonces(){ var elems = document.getElementsByName('nonce'); for (var i=0; i < elems.length; i++){ getNonce(elems[i]); } clearTimeout(t); } window.onload = function(){ t = setTimeout(populateNonces, 5000); } </script> JS; $GLOBALS['JSDelivered'] = true; return $js; } public function getNonce($type='default'){ if (isset($_SESSION['nonce'][$type])){ // } else { $_SESSION['nonce'][$type] = sha1 (uniqid('nonce', true)); } return $_SESSION['nonce'][$type] ; } public function checkNonce($type='default'){ if (empty($_SESSION['nonce'][$type])){ return false; } if (empty($_REQUEST['nonce'])){ return false; } if ($_SESSION['nonce'][$type] == $_POST['nonce']){ unset ($_SESSION['nonce'][$type]); return true; } else { return false; } } public function insertNonceField($type){ $value = getNonce($type); return <<<HTML <input type="hidden" name="nonce" value="$value" /> HTML; } public function insertJSNonceField(){ return <<<HTML {$this->deliverJS()} <input type="hidden" name="nonce" value="" /> HTML; } } if (isset($_POST['action']) && $_POST['action']=="getNonce"){ if (session_id() = '') session_start(); echo nonce::getNonce($_POST['type']); } ?> |
and a sample php file that exemplifies how to use this class
<?php session_start(); require_once 'nonce.php'; $nonce = new nonce; if (isset($_POST['submit'])){ $result = $nonce->checkNonce('form'); if ($result === true){ $msg = 'Your nonce is good'; } else { $msg = 'This is a back button or robot submission'; } } else { $msg = ''; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Nonce Test!</title> </head> <body> <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> <?php echo $nonce->insertJSNonceField(); ?> <input type="submit" name="submit" value="test nonce" /> <div> Wait 5 seconds and click to get a valid nonce. Try clicking straight after a refresh for the robot-type submission; and press refresh to see how this method stops form resubmission. </div> </form> <div style="color:red;"> <? echo $msg;?> </div> </body> </html> |
I’m sure that there’s room for improvement. Let me know!