New and Improved--now built with LylaCaptcha!
In order to try and prevent the spamming issues, I finally had to do something I didn't want to do—and that's implement a Captcha process to the comments.
When you wish to post a comment, you'll now be required to fill in the text you see in the image right below the comment box. This is to help ensure that it's a real person entering in the comment and not just a spam bot. If this doesn't help with the problem, the next step will be either to require a valid e-mail (in which you'll have to go through a verify process the first time you post) or I'll start approving all comments manually. I really hope I don't have to turn off commenting altogether, but I'm tired of deleting 20-30 spam messages a day.
For those of you wondering, I used LylaCaptcha for my captcha needs, which worked on really well. I was going to type up a "how-to", as the documents on the LylaCaptcha site aren't as straightforward as they could be. Once you figure out what you need to do, it's very straightforward, but I found I had to really do a lot through trial an error. Anyway, the reason I'm not doing a write-up is Brian Rinaldi already wrote what I ended up doing in a blog post titled Adding Open-Source LylaCaptcha to BlogCFC.
Don't let that title fool you though, he shows the basic code that's needed to add LylaCaptcha to any of your projects. I just wish I would have found this article before I wrote my code. It would have saved me a lot of trial and error.
NOTE:There are a couple of issues I found with LylaCaptcha.
- The captchaService.cfc must be stored as a persistent variable (application scope, server scope, etc.) This is because it uses a caching algorithm for the hashes. If you only initiate the CFC as a local variable, the results will only be valid for that page. So, if you wish to use a setup like Brian documents in his blog post, make sure to use the application scope.
- If you're on CFMX 6.x, you'll need to remove references to the function isXML() found in the captchaService.cfc. I believe there's only one call to this function. This is a function new to CFMX 7. You can just comment this block of code out—doing so should not harm your code in the least, all it will do is give you less specific error checking if you captcha.xml is invalid.
- This is documented on the LylaCaptcha website. Line 248 that currently reads:
<cfset graphics.setColor(getConfigBean().getFontColor()) />
Should read:
<cfset graphics.setColor(getColorByType(getConfigBean().getFontColor())) />

Comments
1. Yes, the captchaService.cfc must me in a persistent scope. I have made sure that newest documentation (which I haven't released yet) will state that clearly.
2. The isXML() call has been removed for wider application platform support. The things you forgot when you move to newer versions.
3. The bug in regards to setColor() has been fixed in the future releases.
Even better is the Lyla/AjaxCFC article that Brian wrote for CFDJ. Look for it soon!
Best,
.Peter J. Farrell
Great work you put in to LylaCaptcha. It certainly would have taken much more of my time to roll out my own solution. With the changes you've made, I'm sure it'll make it even easier to implement.
It really is easy to use, it was just the few gotchas that I mentioned that took me time to track down. Now that I know what needs to be done, it wouldn't take me but a few minutes to implement the code again.
One suggestion I'd like to see is maybe the use of a dictionary file. Instead of using a random string, it would use a random word from the dictionary (probably should only contain words somewhere between 4-8 characters long.) While not as secure, provided the dictionary is large enough, it should prove secure enough. Heck, you might even make the dictionary of words 3-5 characters long and then combine two words together.
Anyway, great work on the project and thanks for all your hard work!
-Dan
I'm attempting to use lyla but I'm unsure as to how to set the captchaService.cfc as persistant scope. My application.cfm looks like this:
My index.cfm looks like this:
Captcha text:
and my showCaptcha.cfm looks like this:
Yet my image always states that the captcha isn't available. Could anyone help?
Cheers
J
Here's an example of how to configure things so the application scope only gets initialized when it doesn't already exist in memory:
<cflock scope="application" type="readonly" timeout="10">
<cfset bAppInit = structKeyExists(application, "init") />
</cflock>
<cfif NOT bAppInit OR (structKeyExists(url, "reinit") and (url.reinit eq true))>
<cflock scope="application" type="exclusive" timeout="30">
<cfscript>
application.init = true;
// create the captcha service object
application.oCaptchaService = createObject("component", "captchaService").init(configFile="captcha.xml");
// set up the captcha component
application.oCaptchaService.setup();
</cfscript>
</cflock>
</cfif>
Here's what I use to display the code:
<!---// display and delete the image //--->
<cfcontent type="image/jpg" file="#oCaptcha.fileLocation#" deletefile="true" reset="true" />
-Dan
From IE 6 and FF 2 on my other computer, only 1 image is created, a correct one, and is displayed.
My test captcha.cfm is
<CFIF isdefined('form.captchahash')><CFOUTPUT>From form: #application.captcha.validateCaptcha(form.captchaHash,form.captchaText)#<BR></CFOUTPUT></CFIF>
<!--- captcha validation --->
<CFIF isdefined('form.captchaText')>
<CFSET errorStr = "">
<cfif not len(form.captchaText)>
<cfset errorStr = errorStr & "Please enter the Captcha text.<br>">
<cfelseif application.captcha.validateCaptcha(form.captchaHash,form.captchaText) IS "NO">
<cfset errorStr = errorStr & "The captcha text you have entered is incorrect.<br>">
</cfif>
<CFOUTPUT>#errorStr#</CFOUTPUT>
</CFIF>
<cfset application.captcha = CreateObject("component","captchaService").init(configFile="captcha.xml") />
<cfset application.captcha.setup() />
<cfset variables.captcha = application.captcha.createHashReference() />
<BR>
<FORM ACTION="captcha.cfm" METHOD="POST">
<CFOUTPUT>
<img src="#website_url#captcha/captchadisplay.cfm?hashReference=#variables.captcha.hash#" /><BR>
<INPUT TYPE="Text" NAME="captchaHash" VALUE="#variables.captcha.hash#" SIZE="55"><BR> #variables.captcha.text#
Authenticate: <INPUT TYPE="Text" NAME="captchaText" VALUE="" SIZE="10">
</CFOUTPUT>
<INPUT TYPE="Submit" VALUE="Submit">
</FORM>
My captchadisplay.cfm is
<cfset variables.captcha = application.captcha.createCaptchaFromHashReference("file",url.hashReference) />
<cfcontent type="image/jpeg" file="#variables.captcha.fileLocation#" deletefile="false" reset="false" />
Could the dynamic image reference such as
img src="#website_url#captcha/captchadisplay.cfm?hashReference=#variables.captcha.hash#"
be a problem for the spyware detector?
Anyway, in that case, I need to refer to the image differently, I think, somehow.
Any ideas to work around such spyware filters?
Tom
#website_url#captcha/captchadisplay.cfm?hashReference=#variables.captcha.hash#
I'd recommend using an HTTP Proxy filter to actually monitor the HTTP traffic. I'm wonder HTTP call to the image is being called multiple times--like PCcillin is pre-fecthing the content and then IE is grabbing it again.
I'm not sure why 2 different images would be created though...
One other idea, maybe it's a locking issue. Wrap your createCaptchaFromHashReference() call in cflock tags.
In my code I make a locked copy of the Captcha object in the Request scope.
If you are getting double calls to the page, it could be a asynchronous issue. Locking would fix that.
When I use createCaptcha, I can get the captcha to be displayed but haven't figured out how to match it to the text. But, createCaptchaFromHashReference is still creating the two images on that computer even with a lock in place.
You might try contacting Peter Farrell. Perhaps you're using a different version of Captcha. I know I did make a few changes to the CFC (to fix some other issues.)
The id of one I'm using is:
$Id: captchaService.cfc 3221 2006-04-10 21:13:04Z pfarrell $
However, I know I made a few tweaks to the code to fix known issues at the time.
i can't get it work with my hosting server coz it still in CFMX6, i already deleted the "isxml()" function from the captchaservice.cfm file, still can not display the image... :( anyone can help me? i use the newest version (0.2alpha) and the example code on this site:
http://www.dervishmoose.com/blog/index.cfm/2006/9/...
i just replace the "stream" function from the chaptchaimg.cfm file to "file" function like this:
coz it said that the "stream" cannot support in CFMX 6 (only CFMX7), so i use the "file" function... i've been searching for it to support in cfmx 6 but still, can't ><
i just replace the "stream" function from the chaptchaimg.cfm file to "file" function like this:
cfset variables.captcha = application.captcha.createCaptchaFromHashReference("file",url.hashReference)
cfcontent type="image/jpg" file="#variables.captcha.fileLocation#" deletefile="true" reset="false"
(removed the "<" and ">" to display it properly)