Techminded

Adding Captcha in PlayFramework2

Built-in captcha has been gone in PlayFramework2. But to plug-in reCaptcha you may find even easier. I will try to keep my examples as simple as possible and without unnessasarry option you may plug later to improve this approcach. First of gain public and private keys from http://recaptcha.net/, choose option to generate global key in case you are going to debug them on localhost first. Add this keys to cont/application.conf configuration file:

recaptcha.publickey=6Lcpy9YSAAAAAKPK5T8tdO5WbiRPkKENziunk0c2 # recaptcha global public key
recaptcha.privatekey=6Lcpy9YSAAAAANlSJ-iw9GDSKFYX5HktGbs-oG7D # recaptcha global private key

that add recaptcha4j library to your dependencies, place the follogin to your dependency Seq in /project/Build.scala
 

val appDependencies = Seq(
  "net.tanesha.recaptcha4j" % "recaptcha4j" % "0.0.7"
)

than in Play console reload configuratin by execution 'reload' command and check if recaptcha installed successfully by executing 'dependencies' command

Now we need to create view extension as object(singleton) than will be used in templates to display captcha. Create ReCaptcha.scala in /app/views

package views


import java.util.Properties
import net.tanesha.recaptcha.ReCaptchaFactory
import net.tanesha.recaptcha.ReCaptchaImpl
import net.tanesha.recaptcha.ReCaptchaResponse
import play.api.Play.current
import play.api.Logger


object ReCaptcha {

  def publicKey(): String = {
    current.configuration.getString("recaptcha.publickey").get
  }
  def privateKey(): String = {
    current.configuration.getString("recaptcha.privatekey").get
  }
  def render(): String = {
    ReCaptchaFactory.newReCaptcha(publicKey(), privateKey(), false).createRecaptchaHtml(null, new Properties)
  }
}

Object consists of 3 methods: publicKey() and privateKey() to retrieve keys from config file and render() to generate captcha html code.

Now you can check if generation works by adding the following inside your form
 

@Html(views.ReCaptcha.render())

You should see usuall reCaptcha block. Now we should provide user input validity check, add new method to ReCapcha object as follows:

def check(addr: String, challenge: String, response: String): Boolean = {
  val reCaptcha = new ReCaptchaImpl()
  reCaptcha.setPrivateKey(privateKey())
  val reCaptchaResponse = reCaptcha.checkAnswer(addr, challenge, response)
  reCaptchaResponse.isValid()
}

Well this is probably not best idea to place checking code inside views tag, but I promised to keep all this simple and stupid:) play-recaptcha 3rd-party module I used for reference is better designed, so you also can check it to extend your code.

Your form processing code should be wrapped with the following:

 val captchaForm = Form[(String, String)](
  tuple(
     "recaptcha_challenge_field" -> nonEmptyText,
     "recaptcha_response_field" -> nonEmptyText
   )
  )
 captchaForm.bindFromRequest.fold(
   failure => ( BadRequest("Captcha Param Error")),
   { case (q, a) => {
       if (ReCaptcha.check(addr, q, a)) {
         // code in case captcha is valid goes here
       } else {
         BadRequest("Captcha Validation Error")
       }
     }
   }
 )

You can process your application form with model definitions (apply/unapply) as usual without adding captcha fields. 

Comments