Wednesday, 26 July 2006
|
Arithmetic CAPTCHA control
posted at
10:38 PM
|
trackback
|
|
link
Something that's been hanging around a while but I haven't gotten around to posting. If you've ever left a comment on my blog, you know that on the comments page there's a little arithmetic problem, randomly generated, that acts as an anti-comment-spam device. That's a form of a CAPTCHA, which stands for the improbable "completely automated public Turing test to tell computers and humans apart," and which Wikipedia tells me is trademarked by Carnegie-Mellon. Oh.
The most familiar CAPTCHA is the box with the wonky letters on a lo-contrast background, like this:

But a CAPTCHA can consist of anything that nominally requires human intervention. I've been using the little arithmetic test as a CAPTCHA, based on an idea I originally read in a blog comment somewhere.[1]
I've seen a couple of funny ideas for CAPTCHAs. The O'Reilly blog led me to the very un-PC hotcaptcha, which shows pictures of men or women (your choice), and you pick the three who are hot. Try that, CommentSpambot! The O'Reilly blog also led me to this suggestion from the Dive Into Mark site (nws):I need to implement some sort of CAPTCHA based on Strunk & White. If you can’t tell me the difference between “continual” and “continuous,” I don’t want to talk to you. Ha. Anyways, anything you can think of that is easy for humans and hard for machines qualifies, eh?
Update 7 Aug 2006 Mark Liberman on the Language Log was writing about the problems with the infamous Vista speech demo, and said offhand that audio and speech-to-text could likewise be used for CAPTCHA -- again, though, it would not meet accessibility standards.
So, arithmetic quiz. I originally hard-coded it, then rewrote it as an ASP.NET control. You can see the code here. You can play with the control here.
Some notes ... you can control the layout (horizontal, vertical), implemented in a table (sorry). Plus the format ... you can make it something like 2 + 4 = or What is 4 * 3?. You can select an operator or have the control randomly select not just numbers but the operator, too. No divide, tho ... who wants non-integer results?[2] To keep things reasonable, there's an optional separate maximum number for multiplication, because let's face it, no one is going to rassle with What is 19 * 13? just to leave a comment.
The control is easy to use -- just drop it on the page. Somewhere in your code, test its IsValid property, which will be true if the user has provided the correct response. In that sense, it works like ASP.NET validators.
There was some interesting stuff involved in implementing it. I started this control probably around 2 years ago, which is to say, before ASP.NET 2.0. The current implementation inherits from CompositeControl, an option we didn't have in the olde days. So my original implementation inherited from WebControl and rather tediously created controls and their attributes as HTML in the overridden RenderControls method. Ha, none of that any more. Here you just override CreateChildControls and add your controls to the base control's Controls collection.
Eilon suggested to me at one point that I implement the control by inheriting from the base validator control, since it's a kind of validator. But it would have meant (probably) obliging the user to manually put an extra text box on the page and stuff, so in the end, that approach didn't seem like it would get me much.
I found that I had to salt the randomizer for the numbers in the quiz, in case there are multiple instances of the control on the page. (Why would you have multiple instances? Beats me, but mine is not to wonder why.) Initializing the randomization with ticks alone generated the same numbers for all quizzes on the page.
The quiz needs to (re)generate the question at initialization and on reset. I had some problems early on with the question and answer getting out of synch, which turned out to be a problem with storing stuff in viewstate -- changes to the question weren't always being saved to viewstate, because the changes happened after viewstate had been established. The solution was to force viewstate to set a dirty flag so that the change in the property value would get picked up when the page sweeps the controls for viewstate changes.
There was other stuff, too, which I've long since forgotten. Next time I'll take notes as I go to be able to relive every excrutiating mistake, oh boy.
[categories]
aspnet
|