Feature request : Captcha

It will be nice if Captcha or similar mechanism against malicious / automated use , would be available.

Excellent idea! It is already possible to embed Captcha systems such as ReCaptcha, using the Custom HTML features. Once we roll out custom components, you or anyone else can bundle it into a nice, easy Python component.

If you’re feeling brave … :slight_smile:

I started putting this together as a proof of concept, but it’s very, very far from working code. So far it generates text as an image and returns it to be shown on the form. It’s meant to turn it into a 3D plot but I think a special version of matplotlib is required. I was intending to try an alternative but didn’t get very far.

But for what it’s worth, here’s what I was starting to do :

Create Form1 with Image & Button controls
Add this to the Button click event :

  def button_generate_image_click (self, **event_args):
    # This method is called when the button is clicked
    r=anvil.server.call('generate_captcha')
    
    i = self.image_1
    i.source=r['image']

Next, create a server module with this in it :

import tables
from tables import app_tables
import anvil.server
import io

import numpy, pylab
from PIL import Image, ImageDraw, ImageFont
#import matplotlib.axes3d as axes3d
#from matplotlib import axes3d

@anvil.server.callable
def generate_captcha():
  m=anvil.Media()
 
  sz = (50,30) 
  img = Image.new('L', sz, 255)
  drw = ImageDraw.Draw(img)
  font = ImageFont.load_default().font  
  drw.text((5,3), 'text', font=font)
  bs = io.BytesIO()
  img.save(bs,format="png")
  
  row=app_tables.captcha.get(id=1)
  row.update(image=anvil.BlobMedia("image/png",bs.getvalue()))
  return row

# This bit being problematic.
#  X , Y = numpy.meshgrid(range(sz[0]),range(sz[1]))
#  Z = 1-numpy.asarray(img)/255
  
#  fig = pylab.figure()
  #ax = axes3d.Axes3D(fig)
  #ax.plot_wireframe(X, -Y, Z, rstride=1, cstride=1)
  #ax.set_zlim((0,50))
  #fig.savefig('c:/test2.png')

Create Data Tables with a table called “captcha”,and two fields : id & image.

Clicking the button will create an image with the word “text” in it, put it in a Data Tables table and return it to the form for displaying in an image control.

Obviously, lots to do (actually obfuscate it some how, actually capture the text from the user and compare it, etc etc.

Sources :


2 Likes

Wow. I am officially impressed. Would love to see this working.

1 Like

Well, I guess I’ll have to finish it now :slight_smile:

EDIT -
getting there - still a way to go, but :

image

Server module needs to change to be this :

import tables
from tables import app_tables
import anvil.server
import io

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pylab

import numpy
from PIL import Image, ImageDraw, ImageFont

@anvil.server.callable
def generate_captcha():
  m=anvil.Media()
 
  sz = (50,30) 
  img = Image.new('L', sz, 255)
  drw = ImageDraw.Draw(img)
  font = ImageFont.load_default().font  
  drw.text((5,3), 'ANVIL', font=font)

  X , Y = numpy.meshgrid(range(sz[0]),range(sz[1]))
  Z = 1-numpy.asarray(img)/255
  
  fig = pylab.figure()
  ax = Axes3D(fig)
  ax.plot_wireframe(X, -Y, Z, rstride=1, cstride=1)
  ax.set_zlim((0,50))
  
  bs = io.BytesIO()
  fig.savefig(bs,format="png")
  
  row=app_tables.captcha.get(id=1)
  row.update(image=anvil.BlobMedia("image/png",bs.getvalue()))
  return row

For anyone that’s interested this is a work in progress, so please don’t use as-is.

Ok, got some of the basics down. It creates a 3D graphic of the captcha text and checks the user input against it.

It currently just returns True or False if the user input matches, but you need to set a session status and make sure your server side code that does whatever it is you want protected by captcha checks this status before doing it. if you see what I mean …

The graphic is nigh on unreadable at the moment (so I print the text for testing), and it’s way too big (it’s still taking up space for the x/y backgrounds and axes information). I need to somehow make the text stand out a bit more.

Anyone comfortable with graphics manipulation might be able to help here :slight_smile:

https://anvil.works/ide#clone:N34YQQCZHN7J2X7F=2GBDPT6DY357IDYBBHVKKT7K

Latest update (v0.02).

Whilst I learn how to do 3D graphics in matplotlib I have integrated a 2D routine. It’s a rough integration but it seems to work OK. You can read the captcha at least!

Python 2.7 version using “xrange” :
https://anvil.works/ide#clone:62CHFIY36HAHO2AR=GXC3XBVIKDD6LLMCPFX3TLOO

If you want to use Python 3, just change the “xrange” to “range”. Seems that “range” in v3 is the equivalent to “xrange” in v2.

Here’s the source for the 2D routine :

Hi,

Is there any update regarding the captcha?

Thanks

2 Likes

Hey, do we have captcha as a component?