Why?
The purpose of Captcha is to distinguish humans from machines. And the popular way of doing it is to ask the user to write down what he see's. But then the machines got better, so the captcha were made harder to read. Except now its harder for both machines and humans to read.Examples:
http://www.robotnine.com/2009/05/captcha-words-worst-ones-ever.html
http://www.johnmwillis.com/other/top-10-worst-captchas/
How?
There's 3 parts to this- Creating the Math Question & Answer
- Creating the Image from the Math Question
- Verifying if the user responded properly
Now define a view in django that will output our image and the code for the view is
from django.conf import settings from django.http import HttpResponse from StringIO import StringIO import random, os import Image, ImageFont, ImageDraw def index(request): # Load a random font fontslocation = settings.MEDIA_ROOT + "notes/captcha/" fonts = os.listdir(fontslocation) font = ImageFont.truetype(fontslocation + random.choice(fonts), 25) # Create the image with 400x50 size image = Image.new("RGBA", (400, 50), (255,255,255, 0)) draw = ImageDraw.Draw(image) # Draw the text we get from getBasicMath draw.text((0, 0), getBasicMath(request), font=font, fill="#000000") # Create a StringIO that we can use to save the image data = StringIO() image.save(data, format="PNG") # Return the image directly from memory data.seek(0) return HttpResponse(data.read(), mimetype="image/png") def getBasicMath(request): # The 3 types of operators we'll support operator = random.choice(["+", "-", "x"]) # If its multiplication, lets use smaller numbers if (operator == "x"): num1 = random.randint(0, 10) num2 = random.randint(0, 10) # Store the correct answer in session request.session['captcha_answer'] = num1 * num2 else: num1 = random.randint(20, 40) num2 = random.randint(0, 20) # Store the correct answer in session if (operator == "+"): request.session['captcha_answer'] = num1 + num2 else: request.session['captcha_answer'] = num1 - num2 # This is our output return str(num1) + operator + str(num2) + "=";At the beginning we try to load a random font, you need to find some ttf fonts to use and place them in a folder in the MEDIA_ROOT. As you can see I put all my fonts in the "notes/captcha/" folder. To find free ttf fonts you can try 1001 Free Fonts.
And that is all you need to set up, you can change the questions in the getBasicMath function.
To verify the answer
In the getBasicMath function we set the answer in session "captcha_answer", so next time someone answers the captcha question just verify if their answer matches with that session object.Example
Improvement
There is a LOT of room for improvement- Add a background image
- Transform the image
- Changing from numbers to words. Ex: five + ten =