Spring Integration with reCAPTCHA

Sometimes we just need
CAPTCHA, that’s a sad fact. Today we will learn how to integrate with
reCAPTCHA. Because the topic itself isn’t particularly interesting and advanced, we will overengineer a bit (?) by using
Spring Integration to handle low-level details. The decision to use reCAPTCHA by Google was dictated by two factors: (1) it is a moderately good CAPTCHA implementation with decent images with built-in support for visually impaired people and (2) outsourcing CAPTCHA allows us to remain stateless on the server side. Not to mention we help in digitalizing books.

The second reason is actually quite important. Typically you have to generate CAPTCHA on the server side and store the expected result e.g. in user session. When the response comes back you compare expected and entered CAPTCHA solution. Sometimes we don’t want to store any state on the server side, not to mention implementing CAPTCHA isn’t particularly rewarding task. So it is nice to have something ready-made and acceptable.

full source code is as always available, we are starting from a
simple Spring MVC web application without any CAPTCHA. reCAPTCHA is free but requires registration, so the first step is to
sing-up and generate your public/private keys and fill-in
app.properties configuration file in our sample project.

To display and include reCAPTCHA on your form all you have to do is add JavaScript library:
<div id="recaptcha"> </div>
<script src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>

And place reCAPTCHA widget anywhere you like:
    theme: "white",
    lang : 'en'

official documentation is very concise and descriptive, so I am not diving into details of that. When you include this widget inside your
<form/> you will receive two extra fields when user submits:
recaptcha_response_field and
recaptcha_challenge_field. The first is the actual text typed by the user and the second is a hidden token generated per request. It is probably used by reCAPTCHA servers as a session key, but we don’t care, all we have to do is
passing this fields further to reCAPTCHA server. I will use
HttpClient 4 to perform HTTP request to external server and some clever pattern matching in Scala to parse the response:
trait ReCaptchaVerifier {
  def validate(reCaptchaRequest: ReCaptchaSecured): Boolean


class HttpClientReCaptchaVerifier @Autowired()(
                                                  httpClient: HttpClient,
                                                  servletRequest: HttpServletRequest,
                                                  @Value("${recaptcha_url}") recaptchaUrl: String,
                                                  @Value("${recaptcha_private_key}") recaptchaPrivateKey: String
                                                  ) extends ReCaptchaVerifier {

  def validate(reCaptchaRequest: ReCaptchaSecured): Boolean = {
    val post = new HttpPost(recaptchaUrl)
    post.setEntity(new UrlEncodedFormEntity(List(
      new BasicNameValuePair("privatekey", recaptchaPrivateKey),
      new BasicNameValuePair("remoteip", servletRequest.getRemoteAddr),
      new BasicNameValuePair("challenge", reCaptchaRequest.recaptchaChallenge),
      new BasicNameValuePair("response", reCaptchaRequest.recaptchaResponse)))
    val response = httpClient.execute(post)

  private def isReCaptchaSuccess(response: InputStream) = {
    val responseLines = Option(response) map {
    } getOrElse Nil
    responseLines match {
      case "true" :: _ => true
      case "false" :: "incorrect-captcha-sol" :: _=> false
      case "false" :: msg :: _ => throw new ReCaptchaException(msg)
      case resp => throw new ReCaptchaException("Unrecognized response: " + resp.toList)


class ReCaptchaException(msg: String) extends RuntimeException(msg)

The only missing piece is the
ReCaptchaSecured trait encapsulating two reCAPTCHA fields mentioned earlier. In order to secure any web form with reCAPTCHA I am simply extending this model:
trait ReCaptchaSecured {
  @BeanProperty var recaptchaChallenge = ""
  @BeanProperty var recaptchaResponse = ""

class NewComment extends ReCaptchaSecured {
  @BeanProperty var name = ""
  @BeanProperty var contents = ""

The whole
CommentsController.scala is not that relevant. But the result is!


So it works, but obviously it wasn’t really spectacular. What would you say about replacing the low-level HttpClient call with Spring Integration? The
ReCaptchaVerifier interface (trait) remains the same so the client code doesn’t have to be changed. But we refactor
HttpClientReCaptchaVerifier into two separate, small, relatively high-level and abstract classes:
class ReCaptchaFormToHttpRequest @Autowired() (servletRequest: HttpServletRequest, @Value("${recaptcha_private_key}") recaptchaPrivateKey: String) {

  def transform(form: ReCaptchaSecured) = Map(
    "privatekey" -> recaptchaPrivateKey,
    "remoteip" -> servletRequest.getRemoteAddr,
    "challenge" -> form.recaptchaChallenge,
    "response" -> form.recaptchaResponse).asJava


class ReCaptchaServerResponseToResult {

  def transform(response: String) = {
    val responseLines = response.split('\n').toList
    responseLines match {
      case "true" :: _ => true
      case "false" :: "incorrect-captcha-sol" :: _=> false
      case "false" :: msg :: _ => throw new ReCaptchaException(msg)
      case resp => throw new ReCaptchaException("Unrecognized response: " + resp.toList)


Note that we no longer have to implement
ReCaptchaVerifier, Spring Integration will do it for us. We only have to tell how is the framework suppose to use building blocks we have extracted above. I think I haven’t yet described what Spring Integration is and how it works. In few words it is a very pure implementation of
enterprise integration patterns (some may call it ESB). The message flows are described using XML and can be embedded inside standard Spring XML configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"

       <!-- configuration here -->    


In our case we will describe a message flow from
HttpClientReCaptchaVerifier Java interface/Scala trait to the reCAPTCHA server and back. On the way the
ReCaptchaSecured object must be translated into HTTP request and the HTTP response should be translated into meaningful result, returned transparently from the interface.
<gateway id="ReCaptchaVerifier" service-interface="com.blogspot.nurkiewicz.recaptcha.ReCaptchaVerifier" default-request-channel="reCaptchaSecuredForm"/>

<channel id="reCaptchaSecuredForm" datatype="com.blogspot.nurkiewicz.web.ReCaptchaSecured"/>

<transformer input-channel="reCaptchaSecuredForm" output-channel="reCaptchaGoogleServerRequest" ref="reCaptchaFormToHttpRequest"/>

<channel id="reCaptchaGoogleServerRequest" datatype="java.util.Map"/>


<channel id="reCaptchaGoogleServerResponse" datatype="java.lang.String"/>

<transformer input-channel="reCaptchaGoogleServerResponse" ref="reCaptchaServerResponseToResult"/>

Despite the amount of XML, the overall message flow is quite simple. First we define
gateway, which is a bridge between Java interface and Spring Integration message flow. The argument of
ReCaptchaVerifier.validate() later becomes a
message that is sent to
channel. From that channel
ReCaptchaSecured object is passed to a
transformer. The purpose of the transformer is two translate from
ReCaptchaSecured object to Java map representing a set of key-value pairs. Later this map is passed (through
reCaptchaGoogleServerRequest channel) to
http:outbound-gateway. The responsibility of this component is to translate previously created map into an HTTP request and send it to specified address.

When the response comes back, it is sent to
reCaptchaGoogleServerResponse channel. There
ReCaptchaServerResponseToResult transformer takes action, translating HTTP response to business result (boolean). Finally the transformer result is routed back to the gateway. Everything happens synchronously by default so we can still use simple Java interface for reCAPTCHA validation.

Believe it or not, this all works. We no longer use
HttpClient (guess everything is better compared to HttpClient 4 API…) and instead of one "huge" class we have a set of smaller, focused, easy to test classes. The framework handles wiring up and the low-level details. Wonderful?

Let me summarize our efforts by quoting the conclusions from the presentation above:
balance architectural benefits with development effectiveness. Spring Integration is capable of receiving data from various heterogeneous sources like JMS, relational database or even FTP, aggregating, splitting, parsing and filtering messages in multiple ways and finally sending them further with the most exotic protocols. Coding all this by hand is a really tedious and error-prone task. On the other hand sometimes we just don’t need all the fanciness and getting our hands dirty (e.g. by doing a manual HTTP request and parsing the response) is much simpler and easier to understand. Before you blindly base your whole architecture either on very high-level abstractions or on hand-coded low-level procedures: think about the consequences and balance. No solution fits all problems. Which version of reCAPTCHA integration do you find better?

Source : http://www.javacodegeeks.com/2012/05/spring-integration-with-recaptcha.html


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 )

Google+ photo

You are commenting using your Google+ 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 )


Connecting to %s