04
Jan
09

Integrating reCAPTCHA with Castle MonoRail

I’m currently working on a little experimental Castle MonoRail project and wanted to add a CAPTCHA image to a form. Of course I could try to create my own but I don’t like reinventing the wheel so I did a little digging and came across reCAPTCHA. It can be integrated into websites and has a number of tools available to help you do this.

I couldn’t find an example of using it with MonoRail, but did find this example for ASP.NET MVC by Derik Whittaker which pointed me in the right direction. Here’s what I did:

1. Sign up to reCAPTCHA to obtain my private and public keys. I made this a global account so I can test it on my local server rather than only on an assigned domain.

2. Added the keys to my web.config:

<appSettings>
    <add key="recaptcha.public" value="***" />
    <add key="recaptcha.private" value="***" />
</appSettings>

3. Downloaded the ASP.NET library and added a reference to the recaptcha.dll assembly.

3. Created a new helper for rendering the control in the view:

public class CaptchaHelper : AbstractHelper
{
    public string Render()
    {
        var captchaControl = new RecaptchaControl {
              ID = "recaptcha",
              Theme = "blackglass",
              PublicKey = ConfigurationManager.AppSettings["recaptcha.public"],
              PrivateKey = ConfigurationManager.AppSettings["recaptcha.private"]
        };
        var htmlWriter = new HtmlTextWriter( new StringWriter() );
        captchaControl.RenderControl(htmlWriter);
        return htmlWriter.InnerWriter.ToString();
    }
}

4. Added the helper to my controller:

[Helper(typeof(CaptchaHelper), "captcha")]
public class HomeController : SmartDispatcherController
{
    ...
}

5. Called the helper inside a form in my view:

$captcha.Render()

6. Created a new parameter binder (instead of Derik’s filter) that determines if the user entered the CAPTCHA code correctly:

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CaptchaBindAttribute : Attribute, IParameterBinder
{
    private const string CHALLENGE_FIELD_KEY = "recaptcha_challenge_field";
    private const string RESPONSE_FIELD_KEY = "recaptcha_response_field";
    public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
    {
        var captchaChallengeValue = context.Request[CHALLENGE_FIELD_KEY];
        var captchaResponseValue = context.Request[RESPONSE_FIELD_KEY];
        var captchaValidtor = new Recaptcha.RecaptchaValidator
                              {
                                  PrivateKey = ConfigurationManager.AppSettings["recaptcha.private"],
                                  RemoteIP = context.UnderlyingContext.Request.UserHostAddress,
                                  Challenge = captchaChallengeValue,
                                  Response = captchaResponseValue
                              };
        var recaptchaResponse = captchaValidtor.Validate();
        return recaptchaResponse.IsValid;
    }
    public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
    {
        if (parameterInfo.ParameterType == typeof(bool))
            return 10;
        return 0;
    }
}

7. Used the new parameter binder on the receiving controller action to determine if the user passed the CAPTCHA test:

[AccessibleThrough(Verb.Post)]
public void Register([CaptchaBind]bool captchaValid)
{
    ...
}

And that’s about it. I’ll be releasing this project as open source soon (once I’ve made some more progress). I’ve added these components to my AndyPike.Commons assembly which will also be available to those that would like it, but the above code samples should be enough to get you going. Oh, and here is what the view looks like:

recaptcha

recaptcha in action

kick it on DotNetKicks.com


1 Response to “Integrating reCAPTCHA with Castle MonoRail”



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Twitter

  • If you are into Minecraft then tomorrow looks like it might be an epic day: The first 1.9 snapshot is coming (maybe). 😍 1 day ago
  • RT @scinos: Want to troll the frontend devs in your team? Use the username "[object Object]" and send them a screenshot. Enjoy the imaginar… 2 days ago
  • Right, ready to create a @lotus_rb app to try it out properly…. *spends next 20 mins thinking of a name for new project* 4 days ago
  • RT @lotus_rb: The future is bright for us and you, the beloved community, is the key. If you like this tweet, please RT and spread the wor… 1 week ago
  • On the way home from @brightonruby, thanks to @andycroll for a great event and the speakers for a great day! See you all next year 💖❤️💛💙💚💜 1 week ago

My Archives

My Categories


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: