Web design and hosting, database, cloud and social media solutions that deliver business results
  • Business Solutions
    • Robotic Process Automation
    • Software
    • Database Consultancy Services
      • Data Integration
      • Datawarehouse Services
      • Power BI
      • Server Upgrade and DBA Services
    • Web Site Design Services
      • Logo Design
      • Payment Gateways
      • Web Localisation and Translation
      • Web Site Optimisation
      • Web Site Security
      • Technical Tools
    • Cloud Services
      • Amazon Web Services
      • Google Cloud Services
      • Microsoft Azure
    • Microsoft Office
    • Social Media Management and Advice Services
  • Academy
    • Our Test Environment
    • Learning Databases
      • The Basics
      • Get Open Query
      • SQL Server Data
      • SQL Server Maintenance
      • Using SQL Server Dates
      • Using SQL Server Functions
      • Using SQL Server Pivot-Unpivot
      • Technical Tools
    • Learning Web Design
      • Building Ousia Content Management System
      • Using ASP-NET
      • Using CSS
      • Using JavaScript
    • Learning Cloud and IT Services
      • Task Scheduler Error 2147943645
      • Requesting SSL and Generation of PFX file in OpenSSL Simple Steps
    • Using Social Media
      • Asking for a Google Review
      • Changing a Facebook account from personal to business
      • Choosing where to focus Social Media effort
      • Social Media Image Sizes
      • Using Meta Data to set Social Media Images
  • About Us
    • Blog
      • Building an entry level gaming machine
      • Google Core Update Jan 2020
      • Hot Chilli Internet Closure
      • How To Choose Content For Your Website Adverts Leaflets
      • Preventing Online Scam
      • Skimmers of the gig economy
      • The most annoying things about websites on the Internet
      • Top 5 websites for free Vector Graphics
    • Careers
      • Translator English-Portuguese
      • Translator English-Spanish
    • Portfolio
    • Team
      • Adrian Anandan
      • Ali Al Amine
      • Ayse Hur
      • Chester Copperpot
      • Deepika Bandaru
      • Gavin Clayton
      • Sai Gangu
      • Suneel Kumar
      • Surya Mukkamala
English (EN-US)English (EN-GB)हिंदी (HI)italiano (IT)日本語 (JA)Português (PT)

Creation of CAPTCHA Images in .NET

Walkthrough: Creation of Captcha Images in ASP.NET using an SQL Database to process the requests to keep out unwanted guests
If you want to run through this walkthrough, please follow the guide on setting up our test environment.

Experience Level - Intermediate

Captcha Image

Need a Captcha to ensure that your website is not being accessed by a load of unwanted guests or bots?

This is how to create a simple one your self, it may not be the most elaborate, but it will provide at least an extra layer of security to you, and will provide an ever changing result set

This has been built in SQL, with VB.NET and MVC Page Routing.

First we need to create the SQL Table to house all of our results. For high use systems, you will need to create an index on the GUID.

Create Table

CREATE TABLE [dbo].[captcha]([captchaGUID] [varchar](36) NOT NULL,[captchaValue] [varchar](10) NULL,[captchaDateAdded] [datetime] NULL,[captchaDateGuessed] [datetime] NULL)

Add a service page

Next we will create a function to generate a random letter. If you look closely at the bottom, the code will pass back empty strings for a few numbers, this way the generated values will always be of varying length.

The reason we use 40 as the value is to generate a one in 5 chance that the string (with a length of 32) returns a blank value.

Random Letter Function

CREATE FUNCTION [dbo].[GetLetter](@MyInt INT) RETURNS VARCHAR(1) AS BEGINRETURN (SELECT REPLACE(SUBSTRING('ABCDEFGHJKMNPQRTUVQXYZ0123456789', @MyInt,1),'_',''))ENDGOSELECT dbo.GetLetter(ROUND(RAND()*40,0))

Add a service page

Now we will create a stored procedure to send the record back to the web site, this is also where Captcha's that have been guessed will be generated and deleted. In this code, they will be deleted after 30 minutes.

We call the function above 10 times and concatenate the values together, and remove any older guessed values.

Stored Procedure

CREATE PROC [dbo].[NewCaptchaValue] AS BEGINWHILE (SELECT COUNT(*) FROM captcha WHERE captchaDateGuessed IS NULL)<150BEGIN
INSERT INTO captcha(captchaGUID,captchaValue,captchaDateAdded)SELECT NEWID(),dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0)),GETDATE()ENDDELETE FROM captcha WHERE captchaDateGuessed<DATEADD(MINUTE,-30,GETDATE())DECLARE @Newcaptcha VARCHAR(36)=(SELECT TOP 1 captchaGUID FROM captcha WHERE captchaDateGuessed IS NULL)SELECT @NewcaptchaEND

Add a service page

Now we need to create a stored procedure that passes the values provided back to us, and whether the values are correct or not.

I decided to send back a string of Pass/Fail.

Stored Procedure

CREATE PROC [dbo].[CaptchaValue](@captchaGUID VARCHAR(36),@captchaValue VARCHAR(10)) AS BEGINDECLARE @CaptchaValueDB VARCHAR(10)=(SELECT captchaValue FROM captcha WHERE captchaGUID=@captchaGUID)DECLARE @Newcaptcha VARCHAR(36)UPDATE captcha SET captchaDateGuessed=GETDATE() WHERE captchaGUID=@captchaGUIDIF @captchaValue=@CaptchaValueDBBEGINSET @Newcaptcha='Pass'ENDIF @captchaValue<>@CaptchaValueDB OR @CaptchaValueDB IS NULLBEGINSET @Newcaptcha='Fail'ENDSELECT @NewcaptchaEND

Switch to the Academy Project in Visual Studio

CS_1_Add_AppCode.png

A couple of steps to follow here

  • If the project doesn't already have it, add the App_Code folder as per screenshot
  • Right Mouse button on the App_Code folder and select Add>Class
  • A pop-up should appear, call this class Captcha.vb

Right click on this new item and select properties.

Above the Public Class declaration add the following reference;

Imports System.Drawing

Switch to the Academy Project in Visual Studio

The first code we create are two functions to generate the distance the lines draw from the edges of the image box. Add this within the class.
    Private Shared Function GenerateLineNumberY() As Integer        Dim ret As New Integer        ret = (6 * Right((Rnd() * Rnd() * Rnd()), 1)) + 2        Return ret    End Function    Private Shared Function GenerateLineNumberX() As Integer        Dim ret As New Integer        ret = (6 * Right((Rnd() * Rnd() * Rnd()), 1)) + 2        Return ret    End Function

Switch to the Academy Project in Visual Studio

Now two functions for the text, the first sets the spacing between the letters, and the second set the height from the top that the letter will draw.
    Private Shared Function GenerateLineNumberSpace() As Integer        Dim ret As New Integer        ret = (Right(Rnd(), 1)) + 13        Return ret    End Function    Private Shared Function GenerateLineNumberHeight() As Integer        Dim ret As New Integer        ret = (2 * Right((Rnd() * Rnd() * Rnd()), 1)) + 1        Return ret    End Function

Switch to the Academy Project in Visual Studio

Next, we create two functions to generate random pen and brush colours, and a final function to return an image to the response.
    Private Shared Function GenerateRandomPenColor() As System.Drawing.Pen        Dim mypen As New Pen(Brushes.Cyan)        Dim ret As New Integer        ret = Right((Rnd() * Rnd() * Rnd()), 1)        Select Case ret            Case 5, 0, 1                mypen.Color = Color.DarkGray            Case 6, 2                mypen.Color = Color.DarkRed            Case 7, 3, 9                mypen.Color = Color.DarkOliveGreen            Case 8, 4                mypen.Color = Color.DarkOrange        End Select        Return mypen    End Function    Private Shared Function GenerateRandomBrushColor() As System.Drawing.SolidBrush        Dim myBrush As New SolidBrush(Color.Aqua)        Dim ret As New Integer        ret = Right((Rnd() * Rnd() * Rnd()), 1)        Select Case ret            Case 5, 0, 1                myBrush.Color = Color.DarkGray            Case 6, 2                myBrush.Color = Color.DarkRed            Case 7, 3, 9                myBrush.Color = Color.DarkOliveGreen            Case 8, 4                myBrush.Color = Color.DarkOrange        End Select        Return myBrush    End Function    Public Shared Function GenerateCaptcha(CaptchaString As String) As Bitmap        Dim Height As Integer = 60        Dim Width As Integer = 300        Dim objBitmap As Bitmap        Dim objGraphics As Graphics
        Dim oPoint As New PointF        objBitmap = New Bitmap(Width, Height)        objGraphics = Graphics.FromImage(objBitmap)        'Draw Background        objGraphics.FillRectangle(Brushes.White, 0, 0, Width, Height)        objGraphics.DrawRectangle(Pens.Black, 0, 0, Width - 2, Height - 2)        'Draw Text        Dim oFont As New Font("Arial", 20)        Dim spac As Integer = 5        Dim stringInt As Integer = 1        While stringInt <= CaptchaString.Length            spac = spac + GenerateLineNumberSpace()            oPoint = New PointF(spac, GenerateLineNumberHeight)            objGraphics.DrawString(Mid(CaptchaString, stringInt, 1), oFont, GenerateRandomBrushColor, oPoint)            stringInt = stringInt + 1        End While        'White Lines        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        'Draw Lines        objGraphics.DrawLine(GenerateRandomPenColor, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())        objGraphics.DrawLine(GenerateRandomPenColor, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())
        objGraphics.DrawRectangle(Pens.Black, 0, 0, Width - 2, Height - 2)
        Return objBitmap    End Function
Lets now add this service to the routes table we created in the Global.asax file in the initial project phase, to do this add the new route as per below.

Find the sub RegisterRoutes and add a new route (Routes.MapPageRoute) inside.

    Sub RegisterRoutes(ByVal Routes As RouteCollection)        Routes.MapPageRoute("Captcha", "Captcha/{GUID}", "~/Data/Images/CaptchaService.aspx")    End Sub

Add a service page

Now lets create a function that outputs the returned image to the user. Lets start by creating some folders to segregate the data and pages.

To add the data folder, use the following options;

  • Right click on ClaytabaseAcademy and use the Add>New Folder option, name the folder Data.
  • Now add another folder called Images to the Data Folder
  • Next, add a Webform called CaptchaService.aspx to the Images folder

This page will get called by the route handler we created earlier.

Replace Code

Imports System.Data.SqlClientImports ClaytabaseAcademy.GlobalVariablesImports ClaytabaseAcademy.CaptchaImports System.DrawingImports System.Drawing.ImagingPublic Class CaptchaService    Inherits System.Web.UI.Page    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load        Dim captchaguid As String = RouteData.Values("GUID").ToString        Dim con As New SqlConnection(ConStr)        Dim com As New SqlCommand("SELECT captchaValue FROM captcha WHERE captchaGUID='" + captchaguid + "'", con)        con.Open()        Dim CaptchaBitmap As Bitmap = GenerateCaptcha(com.ExecuteScalar)        con.Close()        Response.ClearContent()        Response.ContentType = "image/bmp"        CaptchaBitmap.Save(Response.OutputStream, ImageFormat.Gif)    End SubEnd Class

Add a service page

Create a new folder called Pages to the root of the project by Right Clicking Claytabase Academy and Add > New Folder

Add a new web form called CaptchaView

Create a new web page, and drag in an image control, textbox, button, hiddenfield and a label or copy the code below into the body (HTML Part) of the page.
<body>    <form id="form1" runat="server" style="margin:100px auto;width:300px;padding:10px;background-color:#fff;box-shadow:0 0 3px 0 #222;border-radius: 8px;">        <div style="text-align:center;">            <asp:Image ID="CaptchaImage" runat="server" />        </div>        <div style="text-align:center;">            <asp:TextBox ID="captchaEntered" runat="server"></asp:TextBox>        </div>        <div style="text-align:center;">            <asp:Button ID="captchaSubmit" runat="server" Text="Submit" style="margin:5px auto"/>            <asp:HiddenField ID="captchaGuid" runat="server" />        </div>        <div style="text-align:center;">            <asp:Label ID="captchaResult" runat="server" Text=""></asp:Label>        </div>    </form></body>

Last step is to test that the code works. For this we need to go into the code behind (right click>view code) and update the code behind to what we have below.

This creates a sub that runs on page load, and another that handles the click of the button we added.

Imports System.Data.SqlClientImports ClaytabaseAcademy.GlobalVariablesPublic Class CaptchaView    Inherits System.Web.UI.Page    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load        If Not IsPostBack Then            Using con As New SqlConnection(ConStr)                Using com As New SqlCommand("EXEC dbo.NewCaptchaValue", con)                    con.Open()                    Dim Captcha As String = com.ExecuteScalar                    captchaGuid.Value = Captcha                    CaptchaImage.ImageUrl = "/Captcha/" + Captcha                End Using            End Using        End If    End Sub    Protected Sub GetCaptcha(sender As Object, e As EventArgs) Handles captchaSubmit.Click        If IsPostBack Then            Using con As New SqlConnection(ConStr)                Dim valStr As String = Replace(captchaEntered.Text, "'", "''")                Dim valGUID As String = Replace(captchaGuid.Value, "'", "''")                Response.Write("valStr: " + valStr + "<br>")                Response.Write("valGUID: " + valGUID + "<br>")                Using com As New SqlCommand("EXEC CaptchaValue '" & valGUID & "','" & valStr & "'", con)                    con.Open()                    Dim res As String = com.ExecuteScalar()                    captchaResult.Text = res                End Using                Response.Write("EXEC CaptchaValue '" & valGUID & "','" & valStr & "'")            End Using        End If    End SubEnd Class

Test that it has worked by select Build > Build Solution from the Top Menu

You should now be able to test this in a number of ways;

  • Click on Debug when on the relevant page
  • Right Mouse button on the item within the project explorer and selecting View in Browser
  • Right Mouse button on the page and select View in Browser

Helpful?

Please note, this commenting system is still in final testing.

Author

Website design by Claytabase

This is a section of code that has been modified from Ousia Content Management System code, one of the quickest and most optimised systems on the market, part of our website design services.

These are available with sites starting at around £500.

more: Responsive and fast. Web Development, Design and Hosting with Content Management System
Copyright Claytabase Ltd 2020

Registered in England and Wales 08985867

Site Links

RSSLoginLink Cookie PolicySitemap

Social Media

facebook.com/Claytabaseinstagram.com/claytabase/twitter.com/Claytabaselinkedin.com/company/claytabase-ltd

Get in Touch

+15125961417info@claytabase.comClaytabase USA, 501 Congress Avenue, Suite 150, Austin, Texas, 78701, United States

Partnered With

The settings on this site are set to allow all cookies. These can be changed on our Cookie Policy & Settings page.
By continuing to use this site you agree to the use of cookies.
Ousia Logo
Logout
Ousia CMS Loader