Java implements graphic verification code

Article directory

  • Preface
  • 1. Implementation ideas?
  • 2. Project construction
    • 1. Create project
    • 2. Introduce dependencies
    • 3.Project configuration
    • 4. Create project files
  • 3. Code implementation
    • 1. Create relevant interfaces
    • 2. Implement functions
    • 3. Interface implementation
  • 4. Test
    • 1. Create a test interface in Apifox
    • 2. Test the verification code generation interface
    • 2. Test the login interface

Foreword

This article uses the Hutool official website to generate the image verification code – A set of tools that keep Java sweet.

Graphical CAPTCHA is a security measure used to verify a user’s identity. It works by generating a picture containing random images and text, asking the user to identify and enter the correct information to prove they are a real user and not a computer program. It is designed to prevent malicious behaviors, such as batch registration, login, spamming, etc., to improve the security of the website. Graphical verification codes usually contain randomly generated numbers, letters or symbols, and also add some interference elements, such as curves, noise or interference lines, to increase the difficulty of recognition. Users need to carefully observe the verification code in the image and manually enter the correct information for verification. Only when the user enters the correct verification code can the operation be successfully completed. The purpose of graphical CAPTCHAs is to exclude automated programs or bots and ensure that only real human users complete the verification process. This verification method effectively improves the security of the website, prevents malicious behavior from occurring, and protects users’ personal information.

1. Implementation ideas?

image-20231101112952294

  1. When the front-end login interface is initialized, the graphical verification code generation interface is called, and then the verification code value is stored in redis, and then the verification code key is returned to the front-end page.
  2. The user enters the username and password and the graphical verification code they see, clicks the login button and brings the previously stored key to the backend, retrieves the verification code value from redis and compares it with the entered value, username, password, verification code If all are entered correctly, the login is successful.

2. Project construction

This article uses a login demo built by SpringBoot. The username and password are not stored in the database. Only redis is used to store the verification code information

1. Create project

Create a SpringBoot project

image-20231101112511206

2. Introduce dependencies

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--hutool toolkit-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.2</version>
        </dependency>
    </dependencies>

3. Project configuration

application.yaml

server:
  port: 8080
spring:
  #Redis related configuration
  data:
    redis:
      host: localhost
      port: 6379

4. Create project files

image-20231101112731762

3. Code implementation

Once again, this article is only to implement the verification code login function demo, and does not use data to store user information. The username and password are both written in the code

1. Create relevant interfaces

LoginService interface, used to process login information

public interface LoginService {<!-- -->
    boolean login(String username, String password, String code,String code_key);
}

ValidateCodeService interface, used to generate graphic verification codes

public interface ValidateCodeService {<!-- -->
    Map<String, String> generateValidateCode();
}

2. Implement functions

Login function

package com.validatecode.service.impl;

import com.validatecode.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

/**
 * @Author YZK
 * @Date 2023/11/1
 */
@Service
public class LoginServiceImpl implements LoginService {<!-- -->

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean login(String username, String password, String code,String code_key) {<!-- -->
        //Get the value through the key of the previously set verification code, and then compare it with the verification code entered by the user
        String validateCode = stringRedisTemplate.opsForValue().get("code:validate:" + code_key);
        System.out.println(validateCode);
        if ("admin".equals(username) & amp; & amp; "123456".equals(password) & amp; & amp; code.equals(validateCode)) {<!-- -->
            return true;
        } else {<!-- -->
            return false;
        }
    }
}

Generate verification code

package com.validatecode.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.validatecode.service.ValidateCodeService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author YZK
 * @Date 2023/11/1
 */
@Service
public class ValidateCodeServiceImpl implements ValidateCodeService {<!-- -->
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public Map<String, String> generateValidateCode() {<!-- -->
        //Generate image verification code through tool class
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 20);
        //Verification code value
        String codeValue = circleCaptcha.getCode();
        System.out.println("Verification code is: " + codeValue);
        //Encode the image to base64 and return it
        String imageBase64 = circleCaptcha.getImageBase64();
        String key = UUID.randomUUID().toString().replaceAll("-", "");
        //Save the verification code value into redis and set the expiry date in 5 minutes
        stringRedisTemplate.opsForValue().set("code:validate:" + key, codeValue, 5, TimeUnit.MINUTES);
        Map<String, String> codeMap = Map.of("key", key, "imageBase64", "data:image/png;base64," + imageBase64);
        return codeMap;
    }
}

"data:image/png;base64," + imageBase64 can be directly displayed in HTML using the tag, which will be shown later.

Using StringRedisTemplate is to avoid serialization problems, so that configuration can be eliminated and functions can be implemented as quickly as possible

3. Interface implementation

package com.validatecode.controller;

import com.validatecode.service.LoginService;
import com.validatecode.service.ValidateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * @Author YZK
 * @Date 2023/11/1
 */
@RestController
public class LoginController {<!-- -->
    @Autowired
    LoginService loginService;

    @Autowired
    ValidateCodeService validateCodeService;

    @GetMapping("/login")
    public String login(@RequestParam String input_username,
                        @RequestParam String input_password,
                        @RequestParam String code,
                        @RequestParam String code_key) {<!-- -->
        if (loginService.login(input_username, input_password, code, code_key)) {<!-- -->
            return "Login successful";
        } else {<!-- -->
            return "Login failed";
        }
    }

    @GetMapping("/generateValidateCode")
    public Map<String, String> generateValidateCode() {<!-- -->
        return validateCodeService.generateValidateCode();
    }

}

Attention! ! ! The code_key parameter in the login interface here should be carried directly by the front end instead of input by the user. This is just for demonstration

4. Test

1. Create a test interface in Apifox

Generate verification code interface

image-20231101145952119

Login interface

image-20231101150004087

2. Test the verification code generation interface

Start the service and access /generateValidateCode

Obtained the following results,

{<!-- -->
    "imageBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAAwCAYAAADzRIMRAAAJgklEQVR4Xu2ba2xcxRXHQ0rUT4hvLVIpX1DVVpRKfKiQ4BvhnYS0NC2V6COlAkoqtbRVoYQSAS3GTWlQIaUqLagkDa GFtHbiYDt + YhpM7E1sx8FsYjuO4ySO7fVj/Vjb + zq9Z5eZnT135s7cu3ftXWd/0pF15/xnFCU/38fcm1VgyG3/Oe1YJZaeniufNqrlYBUdoJiK45Tb0/I + HSrhwFdvuNlV6VgOyZRiOYniBJ 3HpCrJpcZUFJUYpvMR1Rp + IxXLi1AUtkZJLGd0IjDcCKFb081aXimJtczoJEDcipCPNd1iE8sPqRhUJnpcIo3uUqaTQDdfhm7NXCmJVYBQUXTllnxLhZTEKiL8EMKPNUywiYX4IReuQUWix0vFxvKtvI odL1sHXubkilasz62ZEjrmFIpYVCZ6XMyIwjiVjOuu2Z2qfCEVC2H7UW7FEvexqEj0ON + oJFKNX0osm1gISmUqlygUg4pEj00ZnYrD7Y + PuCqdPLr + SkYUKl9yacViP5k4qpJBRaLHpjR2ztvE0ZVOHF1/ JVNQYnmBikSPTdlZMW0TR1c6cVg/2HaHtlYaJbE + 4ZE/jXNhOvoWaduGTioEhTHJIStNsJJYFpGFJNz5RFqq9U + OwmIsSSM2nIQRJXHKUd7d /XlexU5JLIujpxb52eqxVydpW4qTMOKZxyknIsqE84tdrqIXC2EyeZEK2VU3y8V6s3GWtqU4CeP2jEWlYnOLWa4lE6v9snrPpSNXsR7/2yQXq2cwSttSTIQxucdi8qjusbA/MRmErq6XoPm9 LXCgah3UN/wQOjp3wMWRNiuhv2z7QUdNLy/G1MUZGOgYho + aB6DrUB8cbzgNJ1uH4GL/BHztS3t57pIUK5GwJNk2mpLq69vS91d1R + fhib9PwqZnxmCddc/13edD8PzeMBzrzdzU64RhYI5J IysURyYUMjHRA5X7boL/VtyiLJQsFOqiU31HFCsejUNv27msMVrdlmTfvLUib1IhOYnVeVULXU + KF6mQ3vMxfrZ64A8hePjFzNOhrH77zylYiCZdieWE6nI3MHAAKipvtYkkq4rK2 + Dc + Wa6hK + I0pz84K xNJFl9UBGEm77yFl3KN8zvsRJJ6P1GF5fq6BVNMBeYJjP8pfJwxCaPrn725wmIxvRy6foqqYaHWy1h1mbE2XcznD1bB/PzY9YZNgaRyKh1fAjq6zfzDF4icTxfUGmwBrtHYHZyHhLxBCRiCZ gZj9jOZBdOhehSvmEs1pktQS5VYE0DhGvy94dilL0ZzpLmmV1T0H06CjORZOoyOTufhJNDMXi9ZgY2/CZ9ycR6uWJaK46uLxMLxampvY8L0x54Dg5Kckg0OgtNzT/m2e7uV2jEN7Kkqu217 q/kDzlJ65avr/08zwats1u + MBLr0U99nHUJDP3jAknmh/vLQlwW3RPhiTNRuOuT/S7c97qnbDuNZOFFrPTZKi1KXf33LdGi0hwD769Y/lDd/bQNP7/6FVt5IetMdfwibWcxHZrj2eP1 /bTtG1qxUCJRqgtlAzRWMOx4J/Pq57XqGaU8qnERmTCBo + VclL7 + fakxmrvuje9Ii6KSSDXuhChWeGyOtrOILcZ5trO2j7Z9w1Gs9ZcPpi57TKrBnwRppKAQN1N/unMiNUYloscqqDBIY9ODXKxwOP3bz nIqgRhid b9sjKx7t46QttSPnPVY7xEZGJV7r + di5VMpv8 + ZDknUBgTEb2KZYLbvBdsYsVGF + H4Fw5zqbq/3ApfXJP/J0A/mF9McrHufVr/eE9lEo9lwlQd3JB1xkJBZDkVoix + yuVWFLd5L2SJl ZiNQ8 + NbVyq2tXvweKZ + ZzeFVL2vHxtVvnJ + VDmS9MHd4zTdhZUKgYblwmDT3ZMrFt2b0qNyXIqUJSHYht5oVziMWVFiJWMJeHUug4u1bErm2Guc8Y3qVQiqcYRvE9iogyNOd + UIvXHMl + a/vH tMG1zVFIxVHJ9eGQbF2vz3o22PiUSGeH5vbVrbaLQsxYVjOb/DfItF7eiuM17gYs18KMeLlXg040w3ZB + qvJDLJU4IrLM1tcyL6D /1ez8GI2IL6yPBNUfBHoVC7cYmCiNTQ9Z/Wuy + pTy4F08Hwg8ZxMFoXIhTDAxz6SSyeVWFLd5L6TEOvdUP5eqfXU9jO8ZpjnPyIRRQbM17ZkzEN4zjU3ZHyAYDcLZ6oEXQqldZhk6qRiYo2ItL k7D/gMZWfa/fUNWX + SXkxvgQNV6nh0ZDRiLxcD8Iy9enSoUiv2kuBXFNP/s9a/SIWNWjf71XEYqq4a3n6GZnKCyOEGzsXgSNm/P7L7/4Peh1OVuLJyAuOXY3EISgmejsLNymn9lesevR7K + dKC4 EQuhcn0cfIPLgnX48K9gZKQNotEZiMcXIBw + DS + cuNMS8G6eef9/v + DzqVwqsVhOvDQyuSimojBM8zmJFbg8swHqpZygophA5 + C7wHueyrwH1NU7Lc6XTLdiIaJcuM1Que/GLLmcqrrm26l7LYaJWCiPTC wGlctUFIZJnknlVa5VVBS35QSVxATZnJNDUfheeebMJSuUr + rDCJ1qw4tYCMrF6npLBvy4T/fpTFPTwzA7a3 + v6rTtIErF0MllIoqISf6SEAvBT2HePRKBJ1 + fhPt + N5baAMWP/ba8NJ76fBn/U6sJVBg VTjkmw/T0IHSf + EvqVU/VwY2pDdS3qtdCa + tWGBqq55uoMpg8VCwqFVKUYtEBP1FJ4oSXOW5wEkbEKUdlEJFJoAIloiVDtSa9JPpJQYuFuBHFTdYrTsKI6HIquVQSyKBrqERRranK + 0FJLJfohGHoclQKEZUIFLq GTBSntWR5vyh4sRATYUwyfqGTRtdnUDEYTjIwZHNlojitJcv7RVGIhaA4MnlU4/lEJ46uLyITBHESQjWHiuK0BkLzflI0YjGYSMshlIhKHtW4EypR2KsZEVUWYaLI5skoiVWgUInosRtQGJU0KIlTn2 EqFJJPqZAVIdYVo + g==",
    "key": "fa1e7431674c48118f79277c8eb662c2"
}

The key-value of the verification code just generated also exists in redis

image-20231101152648406

View verification code picture

image-20231101152546247

image-20231101152529962

2. Test login interface

image-20231101152439267

Successfully logged in