{"id":3072,"date":"2013-08-05T12:00:25","date_gmt":"2013-08-05T19:00:25","guid":{"rendered":"http:\/\/g-liu.com\/blog\/?p=3072"},"modified":"2015-05-01T23:33:13","modified_gmt":"2015-05-02T06:33:13","slug":"walkthrough-captcha-php","status":"publish","type":"post","link":"https:\/\/g-liu.com\/blog\/2013\/08\/walkthrough-captcha-php\/","title":{"rendered":"Walkthrough: Simple anti-robot captcha with PHP"},"content":{"rendered":"<p><em>This post was featured on the <a href=\"http:\/\/phpweekly.com\" target=\"_BLANK\">PHP Weekly newsletter<\/a>, <a href=\"http:\/\/phpweekly.com\/archive\/2013-08-08.html\" target=\"_BLANK\">Aug. 8, 2013<\/a>.<\/em><br \/>\nOn my website, I decided to implement my own anti-robot captcha system for two reasons: 1) I wanted to keep the website code vanilla and 2) I disliked the CAPTCHAs provided by other services that either made you type in Chinese or that didn&#8217;t visually integrate well with the website.<\/p>\n<h1>Pre-flight check<\/h1>\n<p>Before we start, you should have the following ready:<\/p>\n<ul>\n<li>Knowledge of HTML<\/li>\n<li>An HTML form already set up on your website, capable of sending data to another page<br \/>\nExample: <code>&lt;form method=\"POST\" action=\"senddata.php\" ...&gt;<\/code><\/li>\n<li>A text editor, I recommend Notepad++<\/li>\n<li>A PHP installation. Almost all webhosts will have this.<\/li>\n<li>Programming knowledge is a plus, but I will provide plenty of comments on the code.<\/li>\n<\/ul>\n<p>All set? Great, let&#8217;s move on!<br \/>\n<!--more--><\/p>\n<h1>Overview<\/h1>\n<p>So far, we already have an HTML form, which submits data to another PHP page for processing. All we need to do then, is add on a captcha system to the form.<\/p>\n<p>Our captcha will be math based, so it will ask a random math question such as &#8220;What is 3+2?&#8221; or &#8220;What is 8 * 4?&#8221;. There will also be an input box for the user\/robot&#8217;s answer.<\/p>\n<p>We will send the user\/robot&#8217;s answer to the page specified in the <code>form action<\/code> attribute, and check if it matches the actual answer. If it does, we process the form. If not, we stop the process.<\/p>\n<h1>Step 2: Adding the CAPTCHA.<\/h1>\n<p>First of all, we have to be able to generate a random math problem. We&#8217;ll try to keep it simple enough &#8212; no decimals, negative numbers, or algebra &#8212; but random enough so that robots can&#8217;t predict the answer. This basically means we&#8217;ll need:<\/p>\n<ol>\n<li>Two random numbers<\/li>\n<li>A random mathematical operation from the list: addition, multiplication, and subtraction. I left out division because of the possibility of requiring decimals (e.g. 10 divided by 3)<\/li>\n<\/ol>\n<p>In PHP, making random numbers is simple enough. the <a href=\"http:\/\/php.net\/manual\/en\/function.rand.php\"><code>rand(int $min, int $max)<\/code><\/a> function can provide us with random integers. Now how about the operand? The solution is to choose a random number between 0 and 2, and have each number represent a different operand. We can display to the user a plus, minus, or multiplication sign on their end. Thus, we arrive at this code:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n$num1 = rand(0,10); \/\/ pick a random number from 0 to 10 inclusive\r\n$num2 = rand(0,10); \/\/ same idea\r\n$o = rand(0,2); \/\/ 0 = plus, 1 = minus, 2 = multiply\r\n\r\n\/* This function will use the integer value of $operand to show either a plus, minus, or times. *\/\r\nfunction operand($o) {\r\n    switch($o) {\r\n         case 0: return &quot;+&quot;; break;\r\n         case 1: return &quot;-&quot;; break;\r\n         case 2: return &quot;*&quot;; break;\r\n         default: return &quot;?&quot;; break; \/\/Remark: We shouldn't ever get down here.\r\n     }\r\n}\r\n?&gt;\r\n<\/pre>\n<p>You can put this code at the beginning of your form.<\/p>\n<p>For the HTML part, all we need is a label, input field, and three hidden fields to store our two numbers and the integer representing our operand. Here is the bare-bones code. You should add this part to the end of your form, right before the Submit button.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;label for=&quot;math&quot;&gt;What is &lt;?php echo $num1 . &quot;&amp;nbsp;&quot; . operand($o) . &quot;&amp;nbsp;&quot; . $num2 . &quot;?&quot;; ?&gt;&lt;\/label&gt;\r\n&lt;input type=&quot;text&quot; id=&quot;math&quot; name=&quot;userAnswer&quot; size=&quot;3&quot;&gt;&lt;\/input&gt;\r\n&lt;input type=&quot;hidden&quot; name=&quot;num1&quot; value=&quot;&lt;?php echo $num1; ?&gt;&quot;&gt;&lt;\/input&gt;\r\n&lt;input type=&quot;hidden&quot; name=&quot;operand&quot; value=&quot;&lt;?php echo $o; ?&gt;&quot;&gt;&lt;\/input&gt;\r\n&lt;input type=&quot;hidden&quot; name=&quot;num2&quot; value=&quot;&lt;?php echo $num2; ?&gt;&quot;&gt;&lt;\/input&gt;\r\n&lt;br&gt;\r\n&lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;Verify&quot;&gt;&lt;\/input&gt;\r\n<\/pre>\n<p>This warrants a short explanation. Line 2, in essence, displays the math problem in a way that the user can understand it. Line 3 asks for the user\/robot&#8217;s answer. Lines 4-6 hold the math captcha data that will be sent once the user clicks the submit button. This data will be checked against the user\/robot&#8217;s input.<\/p>\n<h1>Step 3: Creating the validation page.<\/h1>\n<p>In the line of code containing the beginning of your form, you should have at least the <code>method<\/code> and <code>action<\/code> attributes already specified. If not, you can use this as an example:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;form action=&quot;submit.php&quot; method=&quot;POST&quot; name=&quot;myForm&quot;&gt;&lt;\/form&gt;\r\n<\/pre>\n<p>You can name the file in the <code>action<\/code> attribute whatever you want, but it MUST end in <code>.php<\/code>.<\/p>\n<p>Now open that file (create it if there is none), and we&#8217;ll begin the validation process.<\/p>\n<h1>Step 4: The validation code<\/h1>\n<p>Now, we need to get the data from the captcha into the PHP for it to process. Recall that in the HTML code of Step 2, we specified four input fields, three of which were hidden. We put a <code>name<\/code> attribute on each of those, and now we can get their <code>value<\/code> attribute in PHP. Copy and paste the following the blank file:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\nif(!isset($_POST&#x5B;&quot;userAnswer&quot;])) {\r\n    exit(&quot;You did not enter an answer! Try again.&quot;); \/\/ Safety check to make sure that the user actually put a value into the CAPTCHA\r\n}\r\n$userAnswer = $_POST&#x5B;&quot;userAnswer&quot;]; \/\/ This is what the client entered\r\n \r\n\/* Compute the actual answer *\/\r\n\/\/ Get the values in our form\r\n$num1 = $_POST&#x5B;&quot;num1&quot;]; \/\/ First number\r\n$num2 = $_POST&#x5B;&quot;num2&quot;]; \/\/ Second number\r\n$o = $_POST&#x5B;&quot;operand&quot;]; \/\/ INTEGER value of our operand (0, 1, or 2; corresponding to +, -, or *, respectively)\r\n \r\n\/\/ Calculate the actual answer\r\n$actual = -999; # Init variable\r\nswitch($o) {\r\n    case 0: $actual = $num1 + $num2; break; \/\/ 0 = Addition\r\n    case 1: $actual = $num1 - $num2; break; \/\/ 1 = Subtraction\r\n    case 2: $actual = $num1 * $num2; break; \/\/ 2 = Multiplication\r\n}\r\n\r\n\/* Check against the user's input and cancel form submission if it's incorrect *\/\r\nif($userAnswer != $actual) {\r\n    exit(&quot;Sorry, you didn't pass the captcha.&quot;);\r\n}\r\n?&gt;\r\n&lt;!-- code to execute on success --&gt;\r\n<\/pre>\n<p>After this bit of code, you can put the desired code to execute. The code will now execute if and only if the user answers the captcha correctly.<\/p>\n<p>It is out of the scope of this post to introduce how to get form data in PHP. If you followed carefully through the code, however, the general idea is to use <code>$_POST[$name]<\/code>, where <code>$name<\/code> is the <code>name<\/code> attribute value of the HTML element.<\/p>\n<h1>Step 5: Congratulations!<\/h1>\n<p>There you are, the simplest way to create a math-based captcha system. It wasn&#8217;t that bad was it?<\/p>\n<h1>Step 6: But wait, there&#8217;s more!<\/h1>\n<p>I&#8217;ve set up a bare-bones demo in my sandbox so that you can see the captcha in action. The demo is at <a href=\"http:\/\/g-liu.com\/sandbox\/captchaform\/\" target=\"_blank\">http:\/\/g-liu.com\/sandbox\/captchaform\/<\/a>.<\/p>\n<p>You can also get the source code files below. Open these in a text editor.<\/p>\n<ul>\n<li>Form page: <a href=\"http:\/\/g-liu.com\/sandbox\/captchaform\/index.phps\" type=\"text\/html\">index.phps<\/a><\/li>\n<li>Validation page: <a href=\"http:\/\/g-liu.com\/sandbox\/captchaform\/submit.phps\" type=\"text\/html\">submit.phps<\/a><\/li>\n<\/ul>\n<p>If you have any questions, feel free to ask in the comments below.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content --><!-- AddThis Related Posts generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>This post was featured on the PHP Weekly newsletter, Aug. 8, 2013. On my website, I decided to implement my own anti-robot captcha system for two reasons: 1) I wanted to keep the website code vanilla and 2) I disliked the CAPTCHAs provided by other services that either made you type in Chinese or that didn&#8217;t visually integrate well with &#8230;<!-- AddThis Advanced Settings generic via filter on wp_trim_excerpt --><!-- AddThis Share Buttons generic via filter on wp_trim_excerpt --><!-- AddThis Related Posts generic via filter on wp_trim_excerpt --><\/p>\n","protected":false},"author":2,"featured_media":5270,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[830,115],"tags":[],"jetpack_publicize_connections":[],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/g-liu.com\/blog\/wp-content\/uploads\/2013\/08\/you-shall-not-pass.jpg","jetpack_shortlink":"https:\/\/wp.me\/p2Zt3y-Ny","_links":{"self":[{"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/posts\/3072"}],"collection":[{"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/comments?post=3072"}],"version-history":[{"count":37,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/posts\/3072\/revisions"}],"predecessor-version":[{"id":5271,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/posts\/3072\/revisions\/5271"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/media\/5270"}],"wp:attachment":[{"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/media?parent=3072"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/categories?post=3072"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/g-liu.com\/blog\/wp-json\/wp\/v2\/tags?post=3072"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}