ASP.NET CAPTCHA Request Dynamic Settings C# Code Example
The ASP.NET Captcha request dynamic settings example project shows how to dynamically adjust BotDetect CAPTCHA configuration, potentially on each Http request made by the client.
First Time Here?
Check the BotDetect Developer Crash Course for key integration steps.
Any code setting Captcha properties in the Captcha.InitializedWebCaptcha
event handler will be executed not only for each protected form GET or POST request (like Captcha configuration code placed in form source would be), but also for each each GET request loading a Captcha image or sound, or making an Ajax Captcha validation call.
If configured values are dynamic (e.g. randomized from a range), they will be re-calculated for each Captcha challenge generated. For example, Captcha ImageStyle
randomized in Captcha.InitializedWebCaptcha
event handler code will change on each Captcha reload button click.
This means your code can reliably keep track of visitor interaction with the Captcha challenge and dynamically adjust its settings. Also, while Captcha.InitializedWebCaptcha
settings apply to all Captcha instances by default, you can also selectively apply them based on CaptchaId.
To show an example of the possible dynamic Captcha configuration adjustments, this code example increases the difficulty of the Captcha test if the visitor associated with the current ASP.NET Session fails a certain number of Captcha validation attempts, and also sets the Captcha locale to Chinese for requests from a certain IP range.
Download the BotDetect ASP.NET CAPTCHA Generator archive to run this example- C#
- VB.NET
Visual Studio 2005-2017 / .NET 2.0 and onwards
Within this page, the root folder of the extracted archive is referred as the <BDC-DIR>
.
This example is in the <BDC-DIR>/lgcy-on-lgcy/examples/t_api-captcha~conf_via-dynamic_config/csharp/
folder; and contains the following files:
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>BotDetect ASP.NET CAPTCHA Options: Request Dynamic Settings Code Example</title> <link type="text/css" rel="Stylesheet" href="StyleSheet.css" /> </head> <body> <form runat="server" class="column" id="form1"> <h1>BotDetect ASP.NET CAPTCHA Options: <br /> Request Dynamic Settings Code Example</h1> <fieldset> <legend>ASP.NET WebForm CAPTCHA Validation</legend> <p class="prompt"> <label for="CaptchaCodeTextBox">Retype the characters from the picture:</label></p> <BotDetect:WebFormsCaptcha runat="server" ID="DynamicCaptcha" UserInputID="CaptchaCodeTextBox" /> <div class="validationDiv"> <asp:TextBox ID="CaptchaCodeTextBox" runat="server"></asp:TextBox> <asp:Button ID="ValidateCaptchaButton" runat="server" /> <asp:Label ID="CaptchaCorrectLabel" runat="server" CssClass="correct"></asp:Label> <asp:Label ID="CaptchaIncorrectLabel" runat="server" CssClass="incorrect"></asp:Label> </div> </fieldset> <div id="output"> <asp:Literal runat="server" ID="StatusLiteral" /> </div> </form> </body>
Default.aspx.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using BotDetect; using BotDetect.Web; public partial class _Default : System.Web.UI.Page { void Page_Init(object sender, EventArgs e) { Captcha.InitializedWebCaptcha += Captcha_InitializedWebCaptcha; } void Captcha_InitializedWebCaptcha(object sender, BotDetect.InitializedWebCaptchaEventArgs e) { Captcha captchaInstance = sender as Captcha; // Captcha.InitializedWebCaptcha event handlers are global and apply to all // Captcha instances // in the application; if some settings need to be apply only to a // particular Captcha // instance, this is how settings can be conditionally applied based on // CaptchaId if (e.CaptchaId == DynamicCaptcha.CaptchaId) { captchaInstance.SoundEnabled = false; } // re-calculated on each image request ImageStyle[] imageStyles = { ImageStyle.Graffiti, ImageStyle.SunAndWarmAir, ImageStyle.Overlap }; captchaInstance.ImageStyle = CaptchaRandomization.GetRandomImageStyle(imageStyles); // dynamic Captcha settings depending on failed validation attempts: // increase Captcha // difficulty according to number of previously failed validations int count = DynamicCaptchaExample.ValidationCounter.GetFailedValidationsCount(); if (count < 3) { captchaInstance.CodeLength = CaptchaRandomization.GetRandomCodeLength(3, 4); captchaInstance.CodeStyle = CodeStyle.Numeric; captchaInstance.CodeTimeout = 600; // 10 minutes } else if (count < 10) { captchaInstance.CodeLength = CaptchaRandomization.GetRandomCodeLength(4, 6) ; captchaInstance.CodeStyle = CodeStyle.Alpha; captchaInstance.CodeTimeout = 180; // 3 minutes } else { captchaInstance.CodeLength = CaptchaRandomization.GetRandomCodeLength(6, 9); captchaInstance.CodeStyle = CodeStyle.Alphanumeric; captchaInstance.CodeTimeout = 60; // 1 minute } // set Captcha locale to Chinese for requests from a certain IP range string ipRange = "223.254."; bool requestFromRangeDetected = false; // have to use HttpContext.Current.Request and not Page.Request because Page // properties won't be set for Captcha image and sound requests serverd // directly // by the BotDetect Captcha HttpHandler if (null != HttpContext.Current.Request && !String.IsNullOrEmpty(HttpContext.Current.Request.UserHostAddress) && HttpContext.Current.Request.UserHostAddress.StartsWith(ipRange)) { requestFromRangeDetected = true; } if (requestFromRangeDetected) { captchaInstance.CodeStyle = CodeStyle.Alpha; captchaInstance.Locale = "cmn"; } } protected void Page_PreRender(object sender, EventArgs e) { // initial page setup if (!IsPostBack) { // set control text ValidateCaptchaButton.Text = "Validate"; CaptchaCorrectLabel.Text = "Correct!"; CaptchaIncorrectLabel.Text = "Incorrect!"; // these messages are shown only after validation CaptchaCorrectLabel.Visible = false; CaptchaIncorrectLabel.Visible = false; } if (IsPostBack) { // validate the Captcha to check we're not dealing with a bot bool isHuman = DynamicCaptcha.Validate(); if (isHuman) { CaptchaCorrectLabel.Visible = true; CaptchaIncorrectLabel.Visible = false; DynamicCaptchaExample.ValidationCounter.ResetFailedValidationsCount(); } else { CaptchaCorrectLabel.Visible = false; CaptchaIncorrectLabel.Visible = true; DynamicCaptchaExample.ValidationCounter.IncrementFailedValidationsCount(); } } // update status display int count = DynamicCaptchaExample.ValidationCounter.GetFailedValidationsCount(); StatusLiteral.Text = String.Format("<p>Failed Captcha validations: {0}</p>", count); if (count < 3) { StatusLiteral.Text += "<p>Dynamic Captcha difficulty: Easy</p>"; } else if (count < 10) { StatusLiteral.Text += "<p>Dynamic Captcha difficulty: Moderate</p>"; } else { StatusLiteral.Text += "<p>Dynamic Captcha difficulty: Hard</p>"; } } }
App_Code\Counter.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace DynamicCaptchaExample { /// <summary> /// Summary description for Counter /// </summary> public static class ValidationCounter { const string FailedValidationsCountKey = "FailedValidationsCountKey"; public static int GetFailedValidationsCount() { int count = 0; object saved = HttpContext.Current.Session[FailedValidationsCountKey]; if (null != saved) { try { count = (int)saved; } catch (InvalidCastException) { // ignore cast errors count = 0; } } return count; } public static void IncrementFailedValidationsCount() { int count = GetFailedValidationsCount(); count++; HttpContext.Current.Session[FailedValidationsCountKey] = count; } public static void ResetFailedValidationsCount() { HttpContext.Current.Session.Remove(FailedValidationsCountKey); } } }
Web.config
<?xml version="1.0"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <configSections> <section name="botDetect" requirePermission="false" type="BotDetect.Configuration.BotDetectConfigurationSection, BotDetect"/> </configSections> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/> <add key="ValidationSettings:UnobtrusiveValidationMode" value="None"/> </appSettings> <system.web> <httpHandlers> <!-- Register the HttpHandler used for BotDetect Captcha requests --> <add verb="GET" path="BotDetectCaptcha.ashx" type="BotDetect.Web.CaptchaHandler, BotDetect"/> </httpHandlers> <!-- Register a custom SessionIDManager for BotDetect Captcha requests --> <sessionState mode="InProc" cookieless="AutoDetect" timeout="20" sessionIDManagerType="BotDetect.Web.CustomSessionIdManager, BotDetect"/> <!-- Session state is required for BotDetect storage; you can also turn if off globally and only enable for BotDetect-protected pages if you prefer --> <pages controlRenderingCompatibilityVersion="4.5" enableSessionState="true"> <controls> <!-- Register the BotDetect tag prefix for easier use in all pages --> <add assembly="BotDetect" namespace="BotDetect.Web.UI" tagPrefix="BotDetect"/> </controls> </pages> <compilation debug="false" targetFramework="4.5"/> <httpRuntime requestValidationMode="4.5" targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <machineKey compatibilityMode="Framework45"/> </system.web> <system.webServer> <validation validateIntegratedModeConfiguration="false"/> <handlers> <!-- Register the HttpHandler used for BotDetect Captcha requests (IIS 7.0+) --> <remove name="BotDetectCaptchaHandler"/> <add name="BotDetectCaptchaHandler" preCondition="integratedMode" verb="GET" path="BotDetectCaptcha.ashx" type="BotDetect.Web.CaptchaHandler, BotDetect"/> </handlers> </system.webServer> <botDetect helpLinkEnabled="true" helpLinkMode="image" /> </configuration>
Current BotDetect Versions
-
BotDetect ASP.NET CAPTCHA
2019-07-22v4.4.2 -
BotDetect Java CAPTCHA
2019-07-22v4.0.Beta3.7 -
BotDetect PHP CAPTCHA
2019-07-22v4.2.5