Captcha in forms

Use CAPTCHA on Forms

A CAPTCHA is one of the most common tests used on the Web to tell a human from a computer in interactions such as filling out web forms. The user is supposed type characters from a distorted image that appears on the screen. The input is evaluated and if correct, the user is presumed to be human.

Captcha Sample

Starting from SP 3 for Version 1.2, C1 CMS has the built-in CAPTCHA functionality, which you can use with web forms rendered by XSLT functions or created on ASP.NET pages.

How to use the C1 CMS CAPTCHA functionality in XSLT functions

Let’s start with the sample XSLT function that implements the C1 CMS CAPTCHA functionality and renders a form on a page.

Following the sample, you will learn the CAPTCHA functions used in the sample in more detail.

Sample XSLT Function

Let’s see the sample of the XSLT function that renders an input web form.

XSLT Function with Captcha

Using this form, the user can submit his/her contact information by filling out the corresponding input fields and the CAPTCHA.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:c1="http://c1.composite.net/StandardFunctions" xmlns:captcha="http://c1.composite.net/Captcha" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xsl">
	<xsl:template match="/">
		<html>
			<head></head>
			<body>
        <!-- Captcha -->
				<xsl:variable name="captcha_encryptedValue" select="captcha:GetEncryptedValue(c1:GetFormData('captcha'))" />
				<xsl:variable name="captcha_value" select="c1:GetFormData('txtCaptcha')" />
				<xsl:variable name="captcha_isPostBack" select="c1:GetFormData('captcha') != ''" />
				<xsl:variable name="captcha_isValid" select="captcha:IsValid($captcha_value, $captcha_encryptedValue)" />
				<xsl:choose>
					<xsl:when test="$captcha_isPostBack and $captcha_isValid">Submitted!
						<xsl:value-of select="captcha:RegisterUsage($captcha_encryptedValue)" />
					</xsl:when>
					<xsl:otherwise>
						<form method="post">
							<br /> Name: 
							<br /> 
							<input type="text" name="txtName" value="{c1:GetFormData('txtName')}" /> 
							<br /> Email: 
							<br /> 
							<input type="text" name="txtEmail" value="{c1:GetFormData('txtEmail')}" /> 
							<br /> Type the characters you see in the picture below: 
							<br /> 
							<img src="{captcha:GetImageUrl($captcha_encryptedValue)}" /> 
							<br /> 
							<input name="captcha" type="hidden" value="{$captcha_encryptedValue}" /> 
							<input type="text" name="txtCaptcha" value="{$captcha_value}" />
							<xsl:if test="$captcha_isPostBack and not($captcha_isValid)"><label style="color:Red"> Not valid</label></xsl:if>
							<br /> 
							<input type="submit" value="Submit" />
						</form>
					</xsl:otherwise>
				</xsl:choose>
			</body>
		</html>
	</xsl:template>
</xsl:stylesheet>
 

Important: To ensure that the same encrypted value is not used more than once, always use the RegisterUsage function. It registers the used encrypted value so that the next time a web form tries to commit it, this value will not be accepted (see the sampe code above).

In the above example:

  1. We have 3 text input elements: txtName, txtEmail, txtCaptcha. The latter gets the user’s CAPTCHA input. We also have 1 hidden input element to hold the encrypted value for our CAPTCHA called captcha.
  2. The <img> element is set to the URL returned by captcha:GetImageUrl.
  3. The form with these fields and elements is placed within the code block that executes if the form has not been posted back (just loaded) or if the CAPTCHA has not been validated.
  4. We have two variables for the value of the CAPTCHA cipher used on the form and the value entered by the user for the CAPTCHA: captcha_encryptedValue and captcha_value.
  5. We also have to two status variables that indicate whether the CAPTCHA value has been posted back (GetFormData('…')) and whether the user’s input has been valid (IsValid). Based on these two values parts of the XSLT code are executed or not.
  6. In the block that executes on a postback provided that the user’s input valid for the CAPTCHA, we output a success message and register the CAPTCHA value as used with RegisterUsage.
  7. If the user’s input is invalid for the CAPTCHA, the user is informed of that (via the corresponding label element).

Now let’s examine the used functionality a bit closer.

Function Overview

Before using the C1 CMS CAPTCHA, you should first add two required XML namespaces to your XSL file to be able to use required functions:

  • xmlns:captcha="http://c1.composite.net/Captcha"
  • xmlns:c1="http://c1.composite.net/StandardFunctions"

As its name suggests, the captcha namespace contains the function necessary to implement CAPTCHA functionality on a web form. The c1 namespace contains the C1 CMS standard functions, one of which we use in our sample.

Now let’s have an overview of the functions that implement the CAPTCHA functionality on a web form.

C1 CMS CAPTCHA Functions

GetEncryptedValue

This function returns the encrypted value ("CAPTCHA cipher") to be used within the form when getting the CAPTCHA image URL (GetImageUrl) and validating the user’s input (IsValid). If its input parameter is an empty string (which is the case when accessed for the first time) or invalid, the function returns a new CAPTCHA cipher; otherwise, the function simply returns the CAPTCHA cipher passed as its input parameter (which is the case on postbacks).

This value is assigned to the hidden CAPTCHA field on the form and initially is empty.

If the encrypted value has not been used within 30 minutes, it becomes invalid - and a new value must be generated.

GetImageUrl

This function returns an URL to a CAPTCHA image to present to the user. It is based on the CAPTCHA cipher (encrypted value) passed as an input parameter.

This image URL is then specified in the <img> element on the form.

IsValid

This function test the user’s input against the CAPTCHA image for match. It returns true if they match; otherwise, false. The return value is evaluated for selecting the proper course of action – accepting or rejecting the form submission.

RegisterUsage

This function registers ("remembers") the used encrypted value so that the next time a web form tries to commit it, this value will not be accepted. By keeping track of used encrypted values, we ensure that the same encrypted value is not allowed to be used more than once.

C1 CMS Standard Functions

GetFormData

This function gets one of the form’s values sent within an HTTP POST request. The value might be further used as input parameters for CAPTCHA or as field values passed when posting a form.

Adding Fields and Variable

As you can see in the sample above, you should first add a number of fields and other elements to your web form, which must include, amongst others:

  • A hidden input control that will hold the CAPTCHA cipher used within the from
  • An image element that will present the generated CAPTCHA image
  • A text box field element that will get the user’s input for the CAPTCHA image

For better code "readability”, you can define a few XSLT variables:

  • A variable that contains a CAPTCHA cipher, obtained by calling the captcha:GetEnriptedValue function
  • A variable that contains the value user has filled the CAPTCHA text box with
  • A variable that indicates whether the CAPTCHA value has been posted back, obtained by checking whether the CAPTCHA cipher field’s value is empty
  • A variable that indicates whether the user’s input for the CAPTCHA image has been valid, obtained by calling the captcha:IsValid function and passing the user’s input and the CAPTCHA cipher in

Putting Things Together

When the user opens the form for the first time:

  1. It calls the captcha:GetEncryptedValue function by passing the hidden CAPTCHA cipher field value in, initially empty. The function returns the CAPTCHA cipher and initialized the corresponding variable with it.
  2. As the form has not been posted back yet and the user’s input (no input actually) can’t possibly validate, a new CAPTCHA cipher will be created here.
  3. Besides, based on the CAPTCHA cipher value, the image URL is returned by the captcha:GetImageUrl and used to present the CAPTCHA image to the user.

When the user fills out the fields as well as supplies the characters from the CAPTCHA image and submits the form:

  1. The user’s input for the CAPTCHA image is validated by the captcha:IsValid function.
  2. As the form has been posted, the postback status is set to true.
  3. The form refreshes and based on the result returned by captcha:IsValid, one of the following scenarios starts:
  • If the user’s input is valid, a "success" message is displayed and the encrypted value is registered as used with captcha:RegisterUsage
  • If the user’s input is invalid, the fields keep their values and a validation error message is displayed at the CAPTCHA input field