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!

Leave a comment

Your comment