Home » Framework » Create and Verify your own Captcha using Java

Create and Verify your own Captcha using Java

Captcha is used for security purposes to identify whether the user is human or bots like automated scripts. Captcha is used in the forms of web applications or websites or mobile apps.

While submitting the form we can easily identify whether the request comes from human or automated scripts like bots with the help of Captcha. For that captcha will be shown in the form and the same need to be verified before submitting the form.

Normally captcha should be an image and which displays some text over it. Only humans can read that through their eyes and submit the same text for verification. But bots or some automated scripts can not read the text.

Many places we can do captcha verification like signup and submitting comments and etc... Google provides reCAPTCHA to secure your website from spam. There are several types of captcha provided by google like image captcha, "I'm not a robot" check box captcha and etc...

Google reCAPTCHA is the best option to secure your website from spam. if you want to know more about this please take a look at reCAPTCHA.

This article is for readers who want to create their own captcha using Java. Let's get into the project now.

Create Your Own image Captcha in Java

First, let us create a maven project with needed dependencies in spring boot using Spring Inializr. The project structure is below

Captcha-Validation-Project-Structure
Captcha-Validation-Project-Structure

pom.xml file is below

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.tipstocode</groupId>
	<artifactId>captchavalidation</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>captchavalidation</name>
	<description>Spring Boot Captcha Validation Project</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.11</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Let's get it into the captcha part now. First, we want to create a Captcha Servlet which is used to generate the image captcha with string and set that captcha as an attribute in HttpServletResponse.

The below servlet snippet is used to create the image captcha.

package com.tipstocode.captcha;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CaptchaServlet extends HttpServlet {
         public static final String FILE_TYPE = "jpeg";      
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException {
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Max-Age", 0);
            response.setContentType("image/jpeg");
            String captchaStr=CaptchaUtil.generateCaptchatMethod2(6);      
            try {
            	int width=200;     	int height=80;            	
            	Color bg = new Color(0,255,255);
            	Color fg = new Color(0,100,0);            	
            	Font font = new Font("Arial", Font.BOLD, 40);
            	BufferedImage cpimg =new BufferedImage(width,height,BufferedImage.OPAQUE);
            	Graphics g = cpimg.createGraphics();
            	g.setFont(font);
                g.setColor(bg);
                g.fillRect(0, 0, width, height);
                g.setColor(fg);
            	g.drawString(captchaStr,30,55);
            	HttpSession session = request.getSession(true);
                session.setAttribute("CAPTCHA", captchaStr);
               OutputStream outputStream = response.getOutputStream();                   
               ImageIO.write(cpimg, FILE_TYPE, outputStream);
               outputStream.close();               
            } catch (Exception e) {
                    e.printStackTrace();
            }
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException {
        	doPost(request, response);
        }
}

In the above program, I created the image using BufferedImage and decoration of image like setting the background color, writing a text on the image using Graphics Method.

For generating captcha text I have put two methods. The first method is generating random numbers and converting the random numbers into hash. The second one is generating captcha text using salt.

In this project, I have used the second method generateCaptchatMethod2(int captchaLength) to generate the captcha text. Both two methods are available in the below snippet you can use as per your need.

package com.tipstocode.captcha;
import java.util.Random;
public class CaptchaUtil {	
public static String generateCaptchaMethod1(){		
Random ranNum=new Random();
int ranNum1=ranNum.nextInt(); // Some randaom numbers are generated here
String hash1 = Integer.toHexString(ranNum1); // convert randaom numbers into hexadeciaml here		
return hash1;		
}
public static String generateCaptchatMethod2(int captchaLength){		
String saltCharacters = "abranNumcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
StringBuffer captchaStrBuff = new StringBuffer();
java.util.Random ranNum = new java.util.Random();
// build a random captchaLength chars salt        
while (captchaStrBuff.length() < captchaLength){
int index = (int) (ranNum.nextFloat() * saltCharacters.length());
captchaStrBuff.append(saltCharacters.substring(index, index+1));
}	
return captchaStrBuff.toString();		    
}	
}

Great!. Everything is finished. Now you are ready to go with your own captcha. Now you have to map the CaptchaServlet in the Spring Boot application like below.

package com.tipstocode.captchavalidation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import com.tipstocode.captcha.CaptchaServlet;

@SpringBootApplication
@ComponentScan(basePackages = {"com.tipstocode.*"})
public class CaptchavalidationApplication {
	@Bean
	public ServletRegistrationBean customServletBean() {
	    ServletRegistrationBean bean = new ServletRegistrationBean(new CaptchaServlet(), "/secure/captcha/captcha.jpg");
	    return bean;
	}
	public static void main(String[] args) {
		SpringApplication.run(CaptchavalidationApplication.class, args);
	}
}

If you are using Spring Web MVC then you have to map the CaptchaServlet in web.xml like below.

<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/secure/captcha/captcha.jpg</url-pattern>
</servlet-mapping>

Now you have created your own captcha in Spring Boot Application. You will be getting your captcha image by this path "/secure/captcha/captcha.jpg" followed by the project context path. In this project, the below URL serves the captcha image.

http://localhost:8080/captchavalidation/secure/captcha/captcha.jpg

Test the Captcha creation and validate the Captcha

Now we want to create the Rest API to verify the captcha. For that, I have created the controller class like below.

package com.tipstocode.controller;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated
public class CaptchaVerificationController {	
@RequestMapping(value = "/verifycaptcha", method = RequestMethod.GET )
public ResponseEntity<String> getProfileById(@RequestParam("captchaText") 
String captchaText,HttpSession session) throws Exception {			
String captcha=(String)session.getAttribute("CAPTCHA");
if(StringUtils.isBlank(captcha)|| (!StringUtils.isBlank(captcha) && !captcha.equals(captchaText))){
captcha="";
return ResponseEntity.ok("Captcha Invalid");
}
else return ResponseEntity.ok("Captcha Valid");				
}
}

Now we test it with postman.

Get Captcha Image.

Url - http://localhost:8080/captchavalidation/secure/captcha/captcha.jpg

Method - Get

Response - Captcha

Get-Captcha-Postman

Validate Captcha

Url - http://localhost:8080/captchavalidation/verifycaptcha?captchaText=9MqGzk

Method - Get

Response - 'Captcha Valid' if matched (or) 'Captcha Invalid' if doesn't match.

Verify-Captcha-Postman

Hope this post is useful for the users those who want to create their own captcha. If you have any queries please keep me updated.

Download the Full Source Code from GitHub

3 thoughts on “Create and Verify your own Captcha using Java

    1. You have to send the captcha string with form data while form submit, Then you have to validate the captcha string in server side. if it is not valid then throw an exception if it is valid then proceed further. Please refer "/verifycaptcha" API in CaptchaVerificationController controller.

Leave a Reply

Your email address will not be published. Required fields are marked *