Java implements image verification code function

1. Background

When implementing the login function, in order to prevent specific program brute force cracking, the otp dynamic verification code record is generally added when the user logs in for safety. The full name of otp verification code otp is One-time Password, also known as dynamic password, which refers to a password that can only be used once on a computer system or other digital devices, and the validity period is only one login session or very short.

Common verification codes are divided into picture verification codes and SMS verification codes, as well as sliding window modules and verification methods for selecting specified objects. The following is an example of image verification code implemented by Java, and the effect is as follows:

insert image description here

2. Implementation steps

1. Add dependencies to maven

pom.xml introduces dependencies:

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>
<dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>easy-captcha</artifactId>
    <version>1.6.2</version>
</dependency>

2、CaptchaController.java

 /**
     * 验证码
     */
    @GetMapping("/captcha/digit")
    @ApiOperation(value = "获取数字验证码", notes = "获取数字验证码", tags = "验证码相关")
    @ApiImplicitParams({
    
    
            @ApiImplicitParam(name = "uuid", value = "uuid", required = true, paramType = "query")
    })
    @PassToken
    public void captcha(HttpServletResponse response, String uuid) throws IOException {
    
    
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        log.info("获取验证码,uuid:{}", uuid);
        //获取图片验证码
        BufferedImage image = captchaService.getCaptcha(uuid);
        log.info("获取验证码,uuid:{},return:{}", uuid, JSON.toJSONString(image));
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }

    @GetMapping("/captcha/graphics")
    @ApiOperation(value = "获取图形验证码", notes = "获取图形验证码", tags = "验证码相关")
    @ApiImplicitParams({
    
    
            @ApiImplicitParam(name = "uuid", value = "uuid", required = true, paramType = "query"),
            @ApiImplicitParam(name = "type", value = "类型 png:png gif:gif cn:中文 cngif:中文gif arithmeti:算术", required = false, paramType = "query")
    })
    public void captcha(HttpServletRequest request, HttpServletResponse response,
                        @RequestParam String uuid,
                        @RequestParam(defaultValue = "arithmeti", required = false) String type) throws Exception {
    
    
        // 设置请求头为输出图片类型
        response.setContentType("image/gif");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        Captcha captcha = null;
        switch (type) {
    
    
            case "png":
                captcha = new SpecCaptcha(130, 48);
                break;
            case "gif":
                // gif类型
                captcha = new GifCaptcha(130, 48);
                break;
            case "cn":
                // 中文类型
                captcha = new ChineseCaptcha(130, 48, 5, new Font("楷体", Font.PLAIN, 28));
                break;
            case "cngif":
                // 中文gif类型
                captcha = new ChineseGifCaptcha(130, 48, 5, new Font("楷体", Font.PLAIN, 28));
                break;
            case "arithmeti":
                // 算术类型
                ArithmeticCaptcha arithmeticCaptcha = new ArithmeticCaptcha(130, 48);
                arithmeticCaptcha.setLen(3);  // 几位数运算,默认是两位
                arithmeticCaptcha.getArithmeticString();  // 获取运算的公式:3+2=?
                arithmeticCaptcha.text();  // 获取运算的结果:5
                captcha = arithmeticCaptcha;
                break;
            default:
                new SpecCaptcha(130, 48);
                break;
        }
        log.info("验证码:{}", captcha.text());
        // 设置字体
//        captcha.setFont(new Font("Verdana", Font.PLAIN, 32));  // 有默认字体,可以不用设置
        // 设置类型,纯数字、纯字母、字母数字混合
        captcha.setCharType(Captcha.TYPE_DEFAULT);

        //缓存验证码
        redisService.set(AuthKeys.AUTH_CAPTCHA, uuid, captcha.text().toLowerCase());
        // 输出图片流
        captcha.out(response.getOutputStream());
    }
}

3. Generate verification code configuration

/**
 * 生成验证码配置
 *
 */
@Configuration
public class KaptchaConfig {
    
    

    @Bean
    public DefaultKaptcha producer() {
    
    
        Properties properties = new Properties();
        //图片边框
        properties.setProperty("kaptcha.border", "no");
        //文本集合,验证码值从此集合中获取
        properties.setProperty("kaptcha.textproducer.char.string", "ABCDEGHJKLMNRSTUWXY23456789");
        //字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", "0,84,144");
        //干扰颜色
        properties.setProperty("kaptcha.noise.color", "0,84,144");
        //字体大小
        properties.setProperty("kaptcha.textproducer.font.size", "30");
        //背景颜色渐变,开始颜色
        properties.setProperty("kaptcha.background.clear.from", "247,255,234");
        //背景颜色渐变,结束颜色
        properties.setProperty("kaptcha.background.clear.to", "247,255,234");
        //图片宽
        properties.setProperty("kaptcha.image.width", "125");
        //图片高
        properties.setProperty("kaptcha.image.height", "35");
        properties.setProperty("kaptcha.session.key", "code");
        //验证码长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        //字体
        properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
        properties.put("kaptcha.textproducer.char.space", "5");
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

4. CaptchaService.java interface

public interface CaptchaService {
    
    
    boolean validate(String uuid, String code);
    BufferedImage getCaptcha(String uuid);
}

5. CaptchaServiceImpl.java implementation class


@Service
@Slf4j
public class CaptchaServiceImpl implements CaptchaService {
    
    
    @Autowired
    private Producer producer;
    @Autowired
    private RedisService redisService;
    @Value("${default-captcha}")
    private String defaultCaptcha;
    
    /**
    * 生成并缓存验证码,返给前端图片
    */
    @Override
    public BufferedImage getCaptcha(String uuid) {
    
    
        if (StringUtils.isEmpty(uuid)) {
    
    
            throw new GlobalException(BasicCodeMsg.PARAMETER_ERROR.setMsg("uuid不能为空"));
        }
        //生成文字验证码
        String code = producer.createText();
        log.info("uuid:{},验证码:{}",uuid,code);
        //缓存验证码
        redisService.set(AuthKeys.AUTH_CAPTCHA, uuid, code);

        return producer.createImage(code);
    }
}

   /**
    * 校验验证码
    */
    @Override
    public boolean validate(String uuid, String code) {
    
    

        //测试环境123456通过验证(可不加)
        if (EnvEnum.dev.name().equals(env) && code.equals(defaultCaptcha)) {
    
    
            return true;
        }

        String cacheCode = redisService.get(AuthKeys.AUTH_CAPTCHA, uuid, String.class);
        if (StringUtils.isEmpty(cacheCode)) {
    
    
            return false;
        }
        //删除缓存验证码
        redisService.delete(AuthKeys.AUTH_CAPTCHA, uuid);
        if (cacheCode.equalsIgnoreCase(code)) {
    
    
            return true;
        }
        return false;
    }

6. Add verification code verification

Add verification code-related verification in the place of login authorization verification, that is, add in the place where the user name and password were originally verified.


        if ("captcha".equals(type)) {
    
    
            LoginVo loginVo = LoginVo.builder().captcha(captcha)
                    .loginName(username)
                    .uuid(uuid).build();
            boolean result = captchaService.validate(uuid, captcha);
            if (!result) {
    
    
                throw new OAuth2Exception("验证码不正确");
            }
            return;

Involved documents

insert image description here

Guess you like

Origin blog.csdn.net/weixin_47061482/article/details/130060608