3/2/11

Integrating reCAPTCHA with ASP.NET MVC 3

Example using reCAPTCHA in an email-contact page.

www.google.com/recaptcha
code.google.com/apis/recaptcha
www.google.com/recaptcha/api/verify


RecaptchaController Class



\controllers\recaptcha\recaptchaController.cs
using System.Web.Mvc;

namespace ExpressionSoftware.Controllers
{
    public class RecaptchaController : Controller
    {
        //********************************************************
        // PRIVATE DATA - DO NOT HARDCODE
        
           const string RECAPTCHA_PRIVATE_KEY = "----------";
           const string EMAIL_ADDRESS = "john@email.com";
        
        //********************************************************

        const string RECAPTCHA_VERIFY_URL = "http://www.google.com/recaptcha/api/verify";
        
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult Default()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public string Default(FormCollection formValues)
        {
            string result = "fail";
            
            //do not submit recaptcha if form vars are null/empty
            if (!(string.IsNullOrEmpty(formValues["recaptcha_challenge_field"]) ||
                  string.IsNullOrEmpty(formValues["recaptcha_response_field"])))
            {
                //alt - validate using web service
                var recaptcha = new ExpressionSoftware.Recaptcha() { PrivateKey = RECAPTCHA_PRIVATE_KEY,
                                                                     VerifyUrl = RECAPTCHA_VERIFY_URL };

                if (recaptcha.Validate(Request.UserHostAddress, formValues["recaptcha_challenge_field"], 
                                                                formValues["recaptcha_response_field"]))
                {
                    result = EMAIL_ADDRESS;  //captcha test passed, show email address
                }
            }
            return result;
        }
    }
}

\views\recaptcha\default.cshtml
<h2>reCAPTCHA Demo for ASP.NET MVC 3</h2>

@using (Html.BeginForm()) {
<input id="b1" type="button" value="Show CAPTCHA" />
<a id="email" />
<div id="captchaDiv"></div>
<input id="submit" type="submit" value="Submit" style="display:none;"/>
<label id="error" style="display:none;">Invalid input, please try again.</label>    
}

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js" type="text/javascript"></script>
<script src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js" type="text/javascript"></script>
<script src="/js/recaptcha.js" type="text/javascript"></script>

\js\recaptcha.js
$(document).ready(function() {
  $("form").submit(
    function(event) {
      event.preventDefault();
      submit(this, updateUI, "html");
    });
  $("#b1").click(showCaptcha);
});

function submit(form, callback, format) {
  $.ajax({url: form.action,
          type: form.method,
          dataType: format,
          data: $(form).serialize(),
          success: callback
         });
}

function updateUI(result) {
  result = $.trim(result);
  
  if (result == "fail") {
    $("#error").show();
    Recaptcha.reload();
    Recaptcha.focus_response_field();
  }
  else {  //success
    $("#email").text(result);
    $("#email")[0].href = "mailto:"+result;
    $("#captchaDiv").hide();
    $("#submit").hide();
    $("#error").hide();
  }
}

function showCaptcha() {
  Recaptcha.create("6LdXGMISAAAAAKbqYwaabU7h1qjwGYEXoEelZjWV",  //api public key
                   "captchaDiv",
                   {
                     theme: "clean",
                     callback: Recaptcha.focus_response_field
                   }
                  );
  $("#b1").hide();
  $("#submit").show();
  return false;
}


Recaptcha Class / Web Service



recaptcha.cs
using System.IO;
using System.Net;
using System.Text;

namespace ExpressionSoftware
{
    public class Recaptcha
    {
        public string VerifyUrl { get; set; }
        public string PrivateKey { get; set; }

        public bool Validate(string remoteIP, string captchaChallenge, string captchaResponse)
        {
            bool result = false;
            string response = GetWebResponse(remoteIP, captchaChallenge, captchaResponse);
            result = response.ToLower().StartsWith("true");  //api response line 1 value: true or false
            return result;
        }

        string GetWebResponse(string remoteIP, string captchaChallenge, string captchaResponse)
        {
            string result = null;

            //convert params to byte array
            var parameters = string.Format("privatekey={0}&remoteip={1}&challenge={2}&response={3}",
                                           PrivateKey, remoteIP, captchaChallenge, captchaResponse);
            byte[] paramData = Encoding.UTF8.GetBytes(parameters);

            var request = (HttpWebRequest)WebRequest.Create(VerifyUrl);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = paramData.Length;
            request.ServicePoint.Expect100Continue = false;
            
            //write param data to request stream
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(paramData, 0, paramData.Length);
                requestStream.Close();
            }

            using (WebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader responseReader = new StreamReader(stream))
                    {
                        result = responseReader.ReadToEnd();
                        responseReader.Close();
                    }
                    stream.Close();
                }
                response.Close();
            }
            return result;
        }
    }
}



No comments:

Post a Comment