Using collective.captcha in custom forms
We are using Plone for some community sites with blogs and newsitems with comments and we were attacked by spambots and found ourselves writing spam-deleting scripts until we found collective.captcha.
collective.captcha provides a very simple browser view to generate captcha images (and also sound-captchas) and to verify user input. We are using it in Plone 2.5.x and also in 3.x (like in this blog) and it works great in both of them.
First of all, you need to include in your buildout, both in eggs and zcml sections of your instance and then run the buildout to get it installed.
Then you need to integrate the captcha generated image and the form to get user input, we use a simple page template for that, called captcha_widget with the following content:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="ataria">
<body>
<span metal:define-macro="captcha">
<div class="field"
tal:define="error errors/captcha|nothing;"
tal:attributes="class python:test(error, 'field error', 'field')">
<label for="captcha" i18n:translate="label_captcha">Captcha</label>
<span class="fieldRequired" title="Required"
i18n:attributes="title"
i18n:domain="plone"
i18n:translate="label_required">(Required)</span>
<div class="formHelp" i18n:translate="help_captcha">
Provide the text in the image. Just to avoid spambots
</div>
<p tal:replace="structure here/@@captcha/image_tag" />
<div>
<input type="text"
name="captcha"
id="captcha"
value="" />
</div>
</div>
</span>
</body>
</html>
The relevant part in this page template is the line in which the captcha image is rendered:
<p tal:replace="structure here/@@captcha/image_tag" />
The first part is completed. Now we just have to check that the user input and the string shown in the captcha are the same. We mainly use collective.captcha together with qPloneComments and we use CMFFormController based forms so we need to create the .cpt with the form in which we include the captcha with the following sentence:
<metal:captcha use-macro="here/captcha_widget/macros/captcha" />
After that you have to write the validator script and tie together with the .metadata file of your form. The script we use is this:
from Products.CMFPlone import PloneMessageFactory as _
captcha = context.REQUEST.get('captcha')
view = context.restrictedTraverse('@@captcha')
if not view.verify(captcha):
state.setError('captcha', _(u'Are you a bot? Try again...'))
state.set(status='failure')
return state
With this, you will have your form protected from spambots.
But collective.captcha has some sort of bug (or at least it has a bug with our configuration) in which zope can't start if you do not override the captcha view in your product. We reported the error in plone-users but had no input about it, so I just reproduce it here.
To get collective.captcha work correctly and zope start, you have to add an overrides.zcml file to your product and add the following ZCML snippet in it:
<browser:page
name="captcha"
for="*"
permission="zope2.Public"
allowed_interface="collective.captcha.browser.interfaces.ICaptchaView"
class="collective.captcha.browser.captcha.Captcha"
/>
So now you know how to protect your hand-made plone forms with collective.captcha.
Indeed this is an old approach we were using on old Plone 2.5 and Plone 3.x sites. Nowadays we use plone.app.discussion and collective.z3cform.norobots for question/answer based captchas.
You may be interested in these other articles
JakiZU! promoting food sustainability
Oct 28, 2024