【Java】EasyCaptcha 封装验证码接口

 

依赖坐标:

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

 

 

参考EasyCaptcha官方文档:

https://gitcode.net/mirrors/whvcse/easycaptcha?utm_source=csdn_github_accelerator

  

先上代码:

package cn.cloud9.server.test.controller;

import cn.cloud9.server.struct.common.BaseController;
import cn.cloud9.server.struct.response.NoApiResult;
import cn.cloud9.server.struct.spring.SpringContextHolder;
import cn.cloud9.server.struct.util.IpUtil;
import cn.cloud9.server.test.model.CaptchaParam;
import com.wf.captcha.SpecCaptcha;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.awt.*;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author OnCloud9
 * @description 验证码测试类
 * @project tt-server
 * @date 2022年11月07日 下午 09:11
 */
@RestController
@RequestMapping("/test/captcha")
public class CaptchaController extends BaseController {
    private static final String captchaKey = "CAPTCHA";
    private static final String separator = "@";
    private static final StringRedisTemplate redisTemplate = SpringContextHolder.getBean(StringRedisTemplate.class);
    private static final ValueOperations<String, String> valOps = redisTemplate.opsForValue();

    /**
     * 获取验证码图片
     * @param param 验证码生成参数对象
     * @throws IOException IO异常
     */
    @NoApiResult
    @GetMapping("get")
    public void createCaptcha(@ModelAttribute CaptchaParam param) throws IOException {
        /* 三个参数分别为宽、高、位数 */
        SpecCaptcha specCaptcha = new SpecCaptcha(param.getWidth(), param.getHeight(), param.getLength());
        /* 设置字体 */
        specCaptcha.setFont(new Font(param.getFontName(), param.getFontStyle(), param.getFontSize()));  // 有默认字体,可以不用设置
        /* 设置类型,纯数字、纯字母、字母数字混合 */
        specCaptcha.setCharType(param.getCharType());

        /* 设置验证码 */
        final String text = specCaptcha.text().toUpperCase();
        final String ipAddr = IpUtil.getIpAddr(request);
        final String key = captchaKey + separator + ipAddr;
        final boolean isUseRedis = param.isUseRedis();
        if (isUseRedis)  valOps.set(key, text, 5 * 60, TimeUnit.SECONDS);
        else request.getSession().setAttribute(key, text);

        /* 输出验证码图片 */
        final boolean isBase64 = param.isBase64();
        if (isBase64) {
            final String base64 = specCaptcha.toBase64();
            response.getWriter().write(base64);
        } else {
            /* 设置请求头为输出图片类型 */
            response.setContentType("image/gif");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            /* 输出验证码图片 */
            specCaptcha.out(response.getOutputStream());
        }
    }

    /**
     * 验证图片验证码 (可以是验证码失效,错误,这里简单判断为true和false)
     * @param verifyCode 图片验证码
     * @param useRedis 是否使用Redis缓存
     * @return 验证结果
     */
    @PostMapping("verify")
    public boolean verifyCaptcha(@RequestParam String verifyCode, @RequestParam(required = false) boolean useRedis) {
        String storeCode = null;
        final String ipAddr = IpUtil.getIpAddr(request);
        final String key = captchaKey + separator + ipAddr;
        if (useRedis) {
            storeCode = valOps.get(key);
        } else {
            final Object attribute = request.getSession().getAttribute(key);
            storeCode = Objects.isNull(attribute) ? "" : String.valueOf(attribute);
        }
        return verifyCode.equalsIgnoreCase(storeCode);
    }
}

 

参数对象:

package cn.cloud9.server.test.model;

import com.wf.captcha.base.Captcha;
import lombok.Data;

import java.awt.*;

/**
 * @author OnCloud9
 * @description
 * @project tt-server
 * @date 2022年11月25日 下午 08:50
 */
@Data
public class CaptchaParam {

    /* 设置宽度,高度,码数长度 */
    private int width = 200;
    private int height = 80;
    private int length = 6;

    /* 字体设置 */
    private String fontName = "Verdana";
    private int fontStyle = Font.PLAIN;
    private int fontSize = 32;

    /**
     * 验证码字符类型设置
     * TYPE_DEFAULT = 1;
     * TYPE_ONLY_NUMBER = 2;
     * TYPE_ONLY_CHAR = 3;
     * TYPE_ONLY_UPPER = 4;
     * TYPE_ONLY_LOWER = 5;
     * TYPE_NUM_AND_UPPER = 6;
     */
    private int charType = Captcha.TYPE_ONLY_NUMBER;

    /* 是否使用base64 默认不使用 */
    private boolean base64 = false;

    /* 是否使用Redis 默认不使用 */
    private boolean useRedis = false;
}

  

我想,其实就算是前后端分离项目,也一样可以用Session存验证码的

手动设置验证码生成参数,前端投送参数来决定验证码的生成和存储

这里多加一个flag判断是否使用Redis存储,接口就更灵活些

 

设置为true时,可以检查是否走Redis了

 

测试校验接口是否走Redis

 

使用Base64编码:

 

posted @ 2022-11-25 23:35  emdzz  阅读(299)  评论(0编辑  收藏  举报