Monday, April 20, 2015

No CAPTCHA reCAPTCHA for ASP.NET WebForms

The code below is an example approach for reCAPTCHA implemented as ASP.NET WebForms control:

/// <summary>
/// NoCaptcha ReCaptcha for WebForms
/// </summary>
/// <remarks>
/// https://developers.google.com/recaptcha/docs/verify
/// </remarks>
public class NoRecaptchaControl : Control
{
    public class APIResponse
    {
        public bool success { get; set; }
        public string[] error_codes { get; set; }
    }
 
    public string PrivateKey { get; set; }
    public string PublicKey { get; set; }
    public string Theme { get; set; }
 
    private const string RESPONSE_FIELD_KEY = "g-recaptcha-response";
 
    public bool IsValid
    {
        get
        {
            try
            {
                var query         = HttpUtility.ParseQueryString( string.Empty );
                query["secret"]   = this.PrivateKey;
                query["response"] = this.Context.Request.Form[RESPONSE_FIELD_KEY];
 
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri( "https://www.google.com/" );
 
                // Add an Accept header for JSON format.
                client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue( "application/json" ) );
 
                HttpResponseMessage httpresponse = 
                   client.GetAsync( string.Format( "recaptcha/api/siteverify?{0}", query.ToString() ) ).Result;
                var response = httpresponse.Content.ReadAsAsync<APIResponse>().Result;
  
                return response.success;
            }
            catch ( Exception ex )
            {                
                return false;
            }
        }
    }
 
    protected override void Render( HtmlTextWriter writer )
    {
        writer.WriteBeginTag( "script" );
 
        writer.WriteAttribute( "src", "https://www.google.com/recaptcha/api.js" );
        writer.WriteAttribute( "async", "true" );
        writer.WriteAttribute( "defer", "true" );
        writer.Write( HtmlTextWriter.TagRightChar );
 
        writer.WriteEndTag( "script" );
 
        writer.WriteBeginTag( "div" );
        writer.WriteAttribute( "class", "g-recaptcha" );
        writer.WriteAttribute( "data-sitekey", this.PublicKey );
        writer.Write( HtmlTextWriter.TagRightChar );
 
        writer.WriteEndTag( "div" );
 
        base.Render( writer );
    }
}

This uses the HttpClient, make sure to reference the Microsoft.AspNet.WebApi.Client package.

The usage is simple, just put the control on your form:

<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="My.Recaptcha.Assembly.Name" %>
 
...
 
<recaptcha:NoRecaptchaControl 
  ID="recaptcha" runat="server" 
  ClientIDMode="Static" Theme="clean" />

set both private and public keys:

protected override void OnPreInit( EventArgs e )
{
    base.OnPreInit( e );
 
    recaptcha.PrivateKey         = "...";
    recaptcha.PublicKey          = "...";
}

and you are done:

protected void button_Click( object sender, EventArgs e )
{
    if ( recaptcha.IsValid )
    {
        ...
    }
    else
    {
        ...
    }
}

No comments: