Login

Captcha without Freetype or the Python Imaging Library (PIL)

Author:
gregb
Posted:
June 3, 2009
Language:
Python
Version:
1.3
Score:
1 (after 3 ratings)

If, like me, you've had trouble installing the Python Imaging Library or FreeType, you may have also had trouble getting a captcha to work. Here's my quick and dirty workaround — be warned, this is very low level security, and shouldn't be used on high-profile sites.

Originally published at http://gregbrown.co.nz/code/django-captcha-without-freetype-or-pil/

Credit to the author of django-simple-captcha, from whom I borrowed most of this code.

Usage

from django import forms
from ABOVE-FILE import CaptchaField

class CaptchaTestForm(forms.Form):
    myfield = forms.TextField()

    security_check = CaptchaField()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from django.forms.fields import CharField, MultiValueField
from django.forms.widgets import TextInput, MultiWidget, HiddenInput
from django import forms
from django.utils.safestring import mark_safe
import hashlib
import random


class CaptchaTextInput(MultiWidget):
	def __init__(self,attrs=None):
		widgets = (
			HiddenInput(attrs),
			TextInput(attrs),
		)
		super(CaptchaTextInput,self).__init__(widgets,attrs)

	def decompress(self,value):
		if value:
			return value.split(',')
		return [None,None]
		
	
	def render(self, name, value, attrs=None):
		ints = (random.randint(0,9),random.randint(0,9),)
		answer = hashlib.sha1(str(sum(ints))).hexdigest()
		#print ints, sum(ints), answer
		
		extra = "What is %d + %d?" % (ints[0], ints[1])
		value = [answer, u'',]
		
		return mark_safe(extra + super(CaptchaTextInput, self).render(name, value, attrs=attrs))


class CaptchaField(MultiValueField):
	widget=CaptchaTextInput
	
	def __init__(self, *args,**kwargs):
		fields = (
			CharField(show_hidden_initial=True), 
			CharField(),
		)
		super(CaptchaField,self).__init__(fields=fields, *args, **kwargs)
	
	def compress(self,data_list):
		if data_list:
			return ','.join(data_list)
		return None
		
		
	def clean(self, value):
		super(CaptchaField, self).clean(value)
		response, value[1] = value[1].strip().lower(), ''
		
		if not hashlib.sha1(str(response)).hexdigest() == value[0]:
			raise forms.ValidationError("Sorry, you got the security question wrong - to prove you're not a spammer, please try again.")
		return value

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

gregb (on June 7, 2009):

Yeah, I linked to that in the description of this snippet... the point of this script is to provide a captcha which doesn't rely on freetype - it uses a plain text question (ie "What is 3 + 4?") instead of an image.

#

Please login first before commenting.