java server generates picture verification code and verification

The requirement is to add a picture verification code when sending SMS verification code.

1. Code implementation

Tool class for generating verification code pictures -- verifyutils java

package com.lmc.utils;

import java.awt.Color;
import java.awt.Font;  
import java.awt.Graphics2D;  
import java.awt.LinearGradientPaint;  
import java.awt.Paint;  
import java.awt.geom.AffineTransform;  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
import java.util.Arrays;  
import java.util.Random;  
  
import javax.imageio.ImageIO;  
  
public class VerifyCodeUtils{  
    // Customizable verification code character source
    public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
  
  
    /** 
     * Generate verification code using system default character source 
     * @param verifySize Verification code length 
     * @return 
     */  
    public static String generateVerifyCode(int verifySize){  
        return generateVerifyCode(verifySize, VERIFY_CODES);  
    }  
    /** 
     * Generates a verification code using the specified source 
     * @param verifySize Verification code length 
     * @param sources   Verification code character source 
     * @return 
     */  
    public static String generateVerifyCode(int verifySize, String sources){  
        if(sources == null || sources.length() == 0){  
            sources = VERIFY_CODES;  
        }  
        int codesLen = sources.length();  
        Random rand = new Random(System.currentTimeMillis());  
        StringBuilder verifyCode = new StringBuilder(verifySize);  
        for(int i = 0; i < verifySize; i++){  
            verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));  
        }  
        return verifyCode.toString();  
    }  
      
    /** 
     * Generate a random verification code file and return the verification code value 
     * @param w Picture width (pixels)
     * @param h Picture height (pixels)
     * @param outputFile 
     * @param verifySize 
     * @return 
     * @throws IOException 
     */  
    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{  
        String verifyCode = generateVerifyCode(verifySize);  
        outputImage(w, h, outputFile, verifyCode);  
        return verifyCode;  
    }  
      
    /** 
     * Output random verification code picture stream and return verification code value 
     * @param w 
     * @param h 
     * @param os 
     * @param verifySize 
     * @return 
     * @throws IOException 
     */  
    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{  
        String verifyCode = generateVerifyCode(verifySize);  
        outputImage(w, h, os, verifyCode);  
        return verifyCode;  
    }  
      
    /** 
     * Generate the specified verification code image file 
     * @param w 
     * @param h 
     * @param outputFile 
     * @param code 
     * @throws IOException 
     */  
    public static void outputImage(int w, int h, File outputFile, String code) throws IOException{  
        if(outputFile == null){  
            return;  
        }  
        File dir = outputFile.getParentFile();  
        if(!dir.exists()){  
            dir.mkdirs();  
        }  
        try{  
            outputFile.createNewFile();  
            FileOutputStream fos = new FileOutputStream(outputFile);  
            outputImage(w, h, fos, code);  
            fos.close();  
        } catch(IOException e){  
            throw e;  
        }  
    }  
      
    /** 
     * Output the specified verification code picture stream 
     * @param w 
     * @param h 
     * @param os 
     * @param code 
     * @throws IOException 
     */  
    public static void outputImage(int w,  
                            int h,  
                            OutputStream os,  
                            String code) throws IOException{  
        int verifySize = code.length();  
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);  
        Random rand = new Random();  
        Graphics2D g2 = image.createGraphics();  
        Color[] colors = new Color[5];  
        Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,  
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,  
                Color.PINK, Color.YELLOW };  
        float[] fractions = new float[colors.length];  
        for(int i = 0; i < colors.length; i++){  
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];  
            fractions[i] = rand.nextFloat();  
        }  
        Arrays.sort(fractions);  
        Paint linearPaint = new LinearGradientPaint(0, 0, w, h, fractions, colors);  
        Paint linearPaint2 = new LinearGradientPaint(0, 0, w, h, new float[]{0.3f, .6f, .8f, .9f}, new Color[]{Color.BLUE, Color.BLACK, Color.GREEN, Color.BLUE});  
        //Set the picture background to white  
        g2.setPaint(Color.WHITE);  
        g2.fillRect(0, 0, w, h);  
        //Set picture gradient background  
        g2.setPaint(linearPaint);  
        g2.fillRoundRect(0, 0, w, h, 5, 5);  
          
        g2.setPaint(linearPaint2);  
        int fontSize = (int) (Math.min(w/verifySize, h));  
        Font font = new Font("Microsoft YaHei ", Font.BOLD, fontSize);  
        g2.setFont(font);  
        char[] chars = code.toCharArray();  
        for(int i = 0; i < verifySize; i++){  
            AffineTransform affine = new AffineTransform();  
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);  
            g2.setTransform(affine);  
            g2.drawChars(chars, i, 1, (w / verifySize) * i, h/2 + fontSize /2);  
        }  
        g2.dispose();  
        ImageIO.write(image, "jpg", os);  
    }  
  
    public static void main(String[] args) throws IOException{  
        File dir = new File("F:/verifies");  
        int w = 200, h = 80;  
        for(int i = 0; i < 100; i++){  
            String verifyCode = generateVerifyCode(4);  
            File file = new File(dir, verifyCode + ".jpg");  
            outputImage(w, h, file, verifyCode);  
        }  
    }  
}  

Generate picture verification code interface and verification interface demo

package com.lmc.controllr;

import com.lmc.utils.VerifyCodeUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description:
 * @Author: lmc
 * @date: 2022/1/1 10:52
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/authCode")
    public void getAuthCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //req.setCharacterEncoding("utf-8");
        //res.setContentType("text/html;charset=utf-8");
        // Set the file MIME type of http response to picture
        response.setContentType("image/jpeg");
        // Do not let the browser record the cache of this picture
        response.setDateHeader("expries", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        // Here, a tool class VerifyCodeUtils is called to generate a verification code string with a specified number of bits (or content)
        String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
        // Save the generated verification code string to the session field for form verification
        request.getSession().setAttribute("verifyCode", verifyCode);
        VerifyCodeUtils.outputImage(60, 30, response.getOutputStream(), verifyCode);
    }

    @RequestMapping("/verifyCode")
    public void verifyCode(String inputVerify, HttpServletRequest request){
        String verifyCode = (String) request.getSession().getAttribute("verifyCode");
        if (inputVerify.equals(verifyCode)){
            System.out.println("The verification code you entered is correct!");
        }else{
            System.out.println("The verification code you entered is incorrect");
        }
    }
}

Test:

Step 1: call the interface to obtain the picture verification code.

Step 2: call the verification interface

The background output is:

Why do I need a picture verification code to get the SMS verification code? (the same is true for other login operations)

When registering enterprise members and applying for game accounts, people find that they sometimes encounter graphic verification codes before obtaining key SMS verification codes. On the surface, it seems that this makes the registration steps more troublesome. In fact, this verification is very popular with enterprises. It is very beneficial to use it together with SMS verification codes. Let's see why.

As we all know, the main function of graphic verification code is to distinguish whether the registration behavior is artificial or machine. For example, before registering Taobao account or buying train tickets and submitting orders, you often have to pass graphic verification before you can obtain the SMS verification code. The main purpose of this step is to prevent malicious attacks by network hackers or criminals using bombing software, Uncontrolled access to SMS verification code, resulting in waste of enterprise cost and bad data of non-human registration. The addition of picture verification code makes the SMS verification code more secure.

In addition to adding graphic verification mechanism in front of SMS verification code, some professional and experienced SMS verification code interface service providers also suggest that enterprises adopt some other security mechanisms, such as the following three:

1. Flow limit during registration

The website allows users to complete registration without applying for SMS verification code, but other operations can be carried out only after verifying the authenticity of identity through mobile SMS verification code. In this way, the registration steps can be separated from obtaining SMS verification code to avoid artificial batch bombing.

2. Add trigger limit

Generally, when registering, you often need to fill in the user name, password and verification code. However, before applying for the SMS verification code, you can add some other restrictions. For example, if the information is not filled in completely or not filled in according to the specified requirements, you will not be able to obtain the SMS verification code.

3. Set request interval( The same mobile phone number can be sent several times a day)

This SMS verification code prevention measure is also used by many websites. Generally, after the initial request for SMS verification code, the second request needs to be sent every one minute or two minutes, or even longer. In addition, in addition to the time limit, the IP limit and the number of requests for the same mobile phone number can also be added.

Graphic verification, time limit and condition limit are added to make the use of SMS verification code safer and more reasonable, so that real users can get a better experience. Generally, regular SMS verification code service providers will remind enterprises to do well in advance.

Original link:

https://www.smshx.com/zixun259.html

https://blog.csdn.net/weixin_34195142/article/details/88923744

Keywords: Java Spring Boot Back-end

Added by Scud on Mon, 03 Jan 2022 02:34:03 +0200