Golang Beego implementing and using CAPTCHA

19 January, 2017

In this small tutorial I'll show you how to use CAPTCHA validation inside your application. We won't be using the builtin CAPTCHA of Beego but instead use another package of GitHub user dchest, and his package captcha.

Prerequisites

Assuming you have your Beego application set and running, go get the captcha package.

go get github.com/dchest/captcha

CAPTCHA controller

Now lets create a controller that generates the CAPTCHA and sends it the the clients browser.

YourBeegoApplication/controllers/Captcha.go

package controllers

import (
	"BeegoCaptchaTutorial/models"
	"bytes"

	"github.com/astaxie/beego"
	"github.com/dchest/captcha"
)

type CaptchaController struct {
	beego.Controller
}

func (this *CaptchaController) Get() {
	// Create a new Captcha
	ValidationString := captcha.New()

	// Store the string for validation later
	models.StoreString = ValidationString

	// Create the captcha image
	var ImageBuffer bytes.Buffer
	captcha.WriteImage(&ImageBuffer, ValidationString, 300, 90)

	// Send Out the headers of the image
	this.Ctx.Output.Header("Cache-Control", "no-cache, no-store, must-revalidate")
	this.Ctx.Output.Header("Pragma", "no-cache")
	this.Ctx.Output.Header("Expires", "0")
	this.Ctx.Output.Header("Content-Type", "image/png")

	// Send out the image itself
	this.Ctx.Output.Body(ImageBuffer.Bytes())
}

The code is self explaining, you create a new CAPTCHA from the package we just downloaded, the New() function returns a string. From this string the package can generate digits for the image, and the other way around, the digits to the original string so we can validate it later.

We store the string in a model, which we still have to create.

Create a bytes buffer to store the generated image in, which the function WriteImage() does. The parameters of this function are

  1. io.Writer, a buffer to save the image in
  2. A string, the string we created with the New function
  3. Width of the image
  4. Heigth of the image

Then we send the correct headers to the client who requests the image. The cache-control is meant so whenever a client refreshes the image, they get served a new one instead of a cached version in their browser.

And last we send the image itself to the client.

Create a model to store the string in

The model itself for this example will be very short, and quite 'static'. In a production environment you'll need some more dynamic storing mechanism, maybe per IP address or by session so every client gets a different key assigned to them.

YourBeegoApplication/models/CaptchaStore.go

package models

var StoreString string

Setup a route

In YourBeegoApplication/routers/route.go init() scope add the following route, so Beego can present the CAPTCHA image to the clients.

beego.Router("/captcha.png", &controllers.CaptchaController{})

Example use

Now lets create a simple form that shows the CAPTCHA image, and asks to fill in the answser. It will look like this:

undefined

Create a template

Create a template file under YourBeegoApplication/views/ folder, in this example I'll use form.tpl

<form method="post">
	<img id=image src="/captcha.png" alt="Captcha image"><br />
	<input type="text" name="captcha">
	<input type="submit" value="Submit">
</form>

{{if .Correct}}Captcha was entered correctly!{{end}}
{{if .Incorrect}}Captcha was wrong, try again!{{end}}

Create a controller for the form

Now we need a controller that shows the form and validates it. My controller is named FormController and saved under YourBeego/controllers/form.go

package controllers

import (
	"BeegoCaptchaTutorial/models"

	"github.com/astaxie/beego"
	"github.com/dchest/captcha"
)

type FormController struct {
	beego.Controller
}

func (this *FormController) Get() {
	this.TplName = "form.tpl"
}

func (this *FormController) Post() {
	// Get the captcha input from the form
	CaptchaInput := this.GetString("captcha")

	// Validate the captcha
	if captcha.VerifyString(models.StoreString, CaptchaInput) {
		this.Data["Correct"] = true
	} else {
		this.Data["Incorrect"] = true
	}

	this.TplName = "form.tpl"
}

We import our models so we can access the CAPTCHA string that gets stored by its controller. We also import the CAPTCHA package because we need the validation function from it. And of course our Beego package.

The Get() function just shows the template, form.tpl on a normal request.

The Post() function gets called whenever the form is posted to this controller.

We validate the input with VerifyString() which takes the following arguments;

  1. The string that was generated by New() in our CaptchaController
  2. The user input from the form

Set up a route to this controller

Again, in YourBeegoApplication/routers/route.go init() scope add the following line.

beego.Router("/form", &controllers.FormController{})

Et voila, you can now go to your webpage/form and see the result!