/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails/index.html
HTML | 355 lines | 220 code | 131 blank | 4 comment | 0 complexity | 79aa04bfbf58497dd461890a58c5f7ea MD5 | raw file
- <!DOCTYPE html>
- <!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
- <!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
- <!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
- <head>
- <meta charset="utf-8">
- <title>Roll your own Ajax-Based Captcha in Grails - coderberry</title>
- <meta name="author" content="Eric Berry">
-
- <meta name="description" content="Recently, I was asked to come up with a better solution to our
- captcha needs. We have been using ReCaptcha, which is great
- but difficult to read at …">
-
- <!-- http://t.co/dKP3o1e -->
- <meta name="HandheldFriendly" content="True">
- <meta name="MobileOptimized" content="320">
- <meta name="viewport" content="width=device-width, initial-scale=1">
-
- <link rel="canonical" href="http://coderberry.me/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails">
- <link href="/favicon.png" rel="icon">
- <link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
- <link href="/atom.xml" rel="alternate" title="coderberry" type="application/atom+xml">
- <script src="/javascripts/modernizr-2.0.js"></script>
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
- <script>!window.jQuery && document.write(unescape('%3Cscript src="./javascripts/lib/jquery.min.js"%3E%3C/script%3E'))</script>
- <script src="/javascripts/octopress.js" type="text/javascript"></script>
- <!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
- <link href="http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
- <link href="http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
-
- <script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-26417518-1']);
- _gaq.push(['_trackPageview']);
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
- </script>
- </head>
- <body >
- <header role="banner"><hgroup>
- <h1><a href="/">coderberry</a></h1>
-
- </hgroup>
- </header>
- <nav role="navigation"><ul class="subscription" data-subscription="rss">
- <li><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
-
- </ul>
-
- <form action="http://google.com/search" method="get">
- <fieldset role="search">
- <input type="hidden" name="q" value="site:coderberry.me" />
- <input class="search" type="text" name="q" results="0" placeholder="Search"/>
- </fieldset>
- </form>
-
- <ul class="main-navigation">
- <li><a href="/">Blog</a></li>
- <li><a href="/blog/archives">Archives</a></li>
- </ul>
- </nav>
- <div id="main">
- <div id="content">
- <div>
- <article class="hentry" role="article">
-
- <header>
-
- <h1 class="entry-title">Roll Your Own Ajax-Based Captcha in Grails</h1>
-
-
- <p class="meta">
-
-
- <time datetime="2010-10-28T00:00:00-06:00" pubdate data-updated="true">Oct 28<span>th</span>, 2010</time>
-
- | <a href="#disqus_thread">Comments</a>
-
- </p>
-
- </header>
- <div class="entry-content"><p>Recently, I was asked to come up with a better solution to our
- captcha needs. We have been using <a href="http://www.google.com/recaptcha">ReCaptcha</a>, which is great
- but difficult to read at times, and has caused frustrated
- customers and lost sales. I found a great solution at
- <a href="http://www.jkdesign.org/captcha">http://www.jkdesign.org/captcha</a> which displays a number of
- graphics and let’s the user choose the right one to prove they
- are human. Here is a screenshot of my implementation:</p>
- <p><img src="/images/posts/Using-Criteria-Builder-with-Projections-1.png"></p>
- <p>To make this work within Grails, I had to make several tweaks. The following files are required:</p>
- <ul>
- <li><a href="http://jqueryui.com/">JQuery 1.2+</a> (I am using version - 1.4.2)</li>
- <li><a href="http://jqueryui.com/">JQuery UI</a> (I am using version - 1.8.2)</li>
- <li><a href="http://gist.github.com/651605">jquery.simpleCaptcha-0.2.js</a></li>
- <li><a href="/files/captchaImages.zip">Captcha Images</a> placed in images/captchaImages</li>
- <li><a href="http://gist.github.com/651613">BCrypt.java</a> by Damien Miller</li>
- <li>CaptchaController.groovy (below)</li>
- </ul>
- <p>Create a new controller called Captcha. This can really be named anything, but if you do rename it, it will have to be updated in the jquery.simpleCaptcha-0.2.js file or passed in as an option via the javascript.</p>
- <div><script src='https://gist.github.com/1291660.js'></script>
- <noscript><pre><code></code></pre></noscript></div>
- <p>What this controller does is return a JSON object with the data needed to generate the captcha. The JSON appears like so:</p>
- <div><script src='https://gist.github.com/1291662.js'></script>
- <noscript><pre><code></code></pre></noscript></div>
- <p>Now we just need to implement this in our GSP file and controller. Suppose we have a page like shown above with a pickup code and the last 4 digits of the persons phone number. With adding our captcha div and required javascript, our GSP would look like this:</p>
- <div><script src='https://gist.github.com/1291664.js'></script>
- <noscript><pre><code></code></pre></noscript></div>
- <p>Finally, we need to perform the validation on the controller side. The modified authentication action would look like the following:</p>
- <figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
- <span class='line-number'>2</span>
- <span class='line-number'>3</span>
- <span class='line-number'>4</span>
- <span class='line-number'>5</span>
- <span class='line-number'>6</span>
- <span class='line-number'>7</span>
- <span class='line-number'>8</span>
- <span class='line-number'>9</span>
- <span class='line-number'>10</span>
- <span class='line-number'>11</span>
- <span class='line-number'>12</span>
- </pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">def</span> <span class="n">pickup</span> <span class="o">=</span> <span class="o">{</span>
- </span><span class='line'>
- </span><span class='line'> <span class="c1">// Determine if the captcha is picked correctly</span>
- </span><span class='line'> <span class="k">if</span> <span class="o">(</span><span class="n">params</span><span class="o">.</span><span class="na">captchaSelection</span> <span class="o">!=</span> <span class="n">session</span><span class="o">.</span><span class="na">selectedCaptchaText</span><span class="o">)</span> <span class="o">{</span>
- </span><span class='line'>
- </span><span class='line'> <span class="c1">// They selected the correct Captcha image. Continue with Authentication</span>
- </span><span class='line'>
- </span><span class='line'> <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
- </span><span class='line'> <span class="n">flash</span><span class="o">.</span><span class="na">message</span> <span class="o">=</span> <span class="s">"You did not click the correct image below. Please Try Again."</span>
- </span><span class='line'> <span class="o">}</span>
- </span><span class='line'>
- </span><span class='line'><span class="o">}</span>
- </span></code></pre></td></tr></table></div></figure>
- <p>So there ya go. It’s actually pretty easy and customers seem to like choosing an image much more than typing a word that is difficult to read.</p>
- </div>
- <footer>
- <p class="meta">
-
-
- <span class="byline author vcard">Posted by <span class="fn">Eric Berry</span></span>
-
-
- <time datetime="2010-10-28T00:00:00-06:00" pubdate data-updated="true">Oct 28<span>th</span>, 2010</time>
-
- <span class="categories">
-
- <a class='category' href='/blog/categories/ajax/'>Ajax</a>, <a class='category' href='/blog/categories/grails/'>Grails</a>, <a class='category' href='/blog/categories/security/'>Security</a>
-
- </span>
- </p>
-
- <div class="sharing">
-
- <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://coderberry.me/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails/" data-via="cavneb" data-counturl="http://coderberry.me/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails/" >Tweet</a>
-
-
-
- <div class="fb-like" data-send="true" data-width="450" data-show-faces="false"></div>
-
- </div>
-
- <p class="meta">
-
- <a class="basic-alignment left" href="/blog/2010/10/12/uploading-files-in-grails/" title="Previous Post: Uploading Files in Grails">« Uploading Files in Grails</a>
-
-
- <a class="basic-alignment right" href="/blog/2010/11/24/paginator-for-those-suffering-from-postgresql-count-star-speed-issues/" title="Next Post: Paginator for those suffering from PostgreSQL count(*) speed issues">Paginator for those suffering from PostgreSQL count(*) speed issues »</a>
-
- </p>
- </footer>
- </article>
- <section>
- <h1>Comments</h1>
- <div id="disqus_thread" aria-live="polite"><noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
- </div>
- </section>
- </div>
- <aside class="sidebar">
-
- <section>
- <h1>Recent Posts</h1>
- <ul id="recent_posts">
-
- <li class="post">
- <a href="/blog/2013/04/23/angularjs-on-rails-4-part-2/">AngularJS on Rails 4 - Part 2</a>
- </li>
-
- <li class="post">
- <a href="/blog/2013/04/22/angularjs-on-rails-4-part-1/">AngularJS on Rails 4 - Part 1</a>
- </li>
-
- <li class="post">
- <a href="/blog/2013/02/20/rubymine-memory-config-vmoptions/">What is the best memory config for RubyMine?</a>
- </li>
-
- </ul>
- </section>
- <section>
- <h1>GitHub Repos</h1>
- <ul id="gh_repos">
- <li class="loading">Status updating...</li>
- </ul>
-
- <a href="https://github.com/cavneb">@cavneb</a> on GitHub
-
- <script type="text/javascript">
- $(document).ready(function(){
- if (!window.jXHR){
- var jxhr = document.createElement('script');
- jxhr.type = 'text/javascript';
- jxhr.src = '/javascripts/libs/jXHR.js';
- var s = document.getElementsByTagName('script')[0];
- s.parentNode.insertBefore(jxhr, s);
- }
- github.showRepos({
- user: 'cavneb',
- count: 3,
- skip_forks: true,
- target: '#gh_repos'
- });
- });
- </script>
- <script src="/javascripts/github.js" type="text/javascript"> </script>
- </section>
-
- </aside>
- </div>
- </div>
- <footer role="contentinfo"><p>
- Copyright © 2013 - Eric Berry -
- <span class="credit">Powered by <a href="http://octopress.org">Octopress</a></span>
- </p>
- </footer>
-
- <script type="text/javascript">
- var disqus_shortname = 'coderberry';
-
-
- // var disqus_developer = 1;
- var disqus_identifier = 'http://coderberry.me/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails/';
- var disqus_url = 'http://coderberry.me/blog/2010/10/28/roll-your-own-ajax-based-captcha-in-grails/';
- var disqus_script = 'embed.js';
-
- (function () {
- var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
- dsq.src = 'http://' + disqus_shortname + '.disqus.com/' + disqus_script;
- (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
- }());
- </script>
- <div id="fb-root"></div>
- <script>(function(d, s, id) {
- var js, fjs = d.getElementsByTagName(s)[0];
- if (d.getElementById(id)) {return;}
- js = d.createElement(s); js.id = id; js.async = true;
- js.src = "//connect.facebook.net/en_US/all.js#appId=212934732101925&xfbml=1";
- fjs.parentNode.insertBefore(js, fjs);
- }(document, 'script', 'facebook-jssdk'));</script>
- <script type="text/javascript">
- (function(){
- var twitterWidgets = document.createElement('script');
- twitterWidgets.type = 'text/javascript';
- twitterWidgets.async = true;
- twitterWidgets.src = 'http://platform.twitter.com/widgets.js';
- document.getElementsByTagName('head')[0].appendChild(twitterWidgets);
- })();
- </script>
- </body>
- </html>