Open-Starter-Captcha

一个支持生成图片验证码,短信验证码,算数图片验证码的插件

🍪 快速开始

欢迎阅读 Open-Starter-Captcha 文档!

如果你有任何与 Open-Starter-Captcha 相关的问题,欢迎随时在 GitHub Discussions 上向我们的社区寻求帮助。

1. 添加 Maven 依赖

<dependency>
    <groupId>com.saucesubfresh</groupId>
    <artifactId>open-starter-captcha</artifactId>
    <version>1.0.3</version>
</dependency>

2. 配置验证码相关参数

com:
  saucesubfresh:
    captcha:
      image:
        length: 4 #图形验证码的位数为6,将覆盖默认配置中的4
        width: 200 #图形验证码的宽度为100,将覆盖默认配置中的67,但由于请求中设置的宽度为200,所以真正的宽度将为200
        height: 60
      scan:
        width: 300 #二维码宽度
        height: 300 #二维码高度
        margin: 1 #二维码外边距,0到4

3. 生成验证码并发送

节选自 Open-Job

@Slf4j
@Validated
@RestController
@RequestMapping("/captcha")
public class OpenJobCaptchaController {

    private final ImageCodeGenerator imageCodeGenerator;
    private final SmsCodeGenerator smsCodeGenerator;

    public OpenJobCaptchaController(ImageCodeGenerator imageCodeGenerator, SmsCodeGenerator smsCodeGenerator) {
        this.imageCodeGenerator = imageCodeGenerator;
        this.smsCodeGenerator = smsCodeGenerator;
    }

    @PostMapping("/create/image")
    public Result<OpenJobCaptchaRespDTO> createImageCode(@RequestBody @Valid OpenJobCaptchaRequest request) {
        OpenJobCaptchaRespDTO openJobCaptchaRespDTO = new OpenJobCaptchaRespDTO();
        CaptchaGenerateRequest captchaGenerateRequest = new CaptchaGenerateRequest();
        captchaGenerateRequest.setRequestId(request.getDeviceId());
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            ImageValidateCode imageValidateCode = imageCodeGenerator.create(captchaGenerateRequest);
            ImageIO.write(imageValidateCode.getImage(), "JPEG", byteArrayOutputStream);
            byte[] bytes = byteArrayOutputStream.toByteArray();
            String base64ImgCode = Base64Utils.encodeToString(bytes);
            openJobCaptchaRespDTO.setImageCode(base64ImgCode);
            openJobCaptchaRespDTO.setSuccess(true);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new ControllerException(e.getMessage());
        }
        return Result.succeed(openJobCaptchaRespDTO);
    }

    @PostMapping("/create/sms")
    public Result<OpenJobCaptchaRespDTO> createSmsCode(@RequestBody @Valid OpenJobCaptchaRequest request) {
        OpenJobCaptchaRespDTO openJobCaptchaRespDTO = new OpenJobCaptchaRespDTO();
        CaptchaGenerateRequest captchaGenerateRequest = new CaptchaGenerateRequest();
        captchaGenerateRequest.setRequestId(request.getDeviceId());
        try {
            ValidateCode validateCode = smsCodeGenerator.create(captchaGenerateRequest);
            openJobCaptchaRespDTO.setSuccess(true);
            log.info("向手机号: {}发送短信验证码: {}", request.getMobile(), validateCode.getCode());
        } catch (ValidateCodeException e) {
            log.error(e.getMessage(), e);
            throw new ControllerException(e.getMessage());
        }
        return Result.succeed(openJobCaptchaRespDTO);
    }
}

扩展示例

1. 替换原有的验证码生成方式

比如要替换掉原来的短信验证码生成方式

@Component
public class ImageCodeGenerator extends AbstractCaptchaGenerator<ImageValidateCode> {

  private final CaptchaProperties captchaProperties;
  private final KaptchaProducer kaptchaProducer;

  public ImageCodeGenerator(CaptchaRepository captchaRepository,
                            CaptchaProperties captchaProperties,
                            KaptchaProducer kaptchaProducer) {
    super(captchaRepository);
    this.captchaProperties = captchaProperties;
    this.kaptchaProducer = kaptchaProducer;
  }

  @Override
  public ImageValidateCode generate() throws ValidateCodeException {
    String text = kaptchaProducer.createText();
    BufferedImage image = kaptchaProducer.createImage(text);
    return new ImageValidateCode(image, text, captchaProperties.getImage().getExpireTime());
  }
}

2. 扩展验证码存储方式(CaptchaRepository)

@Component
public class XxxCaptchaRepository implements CaptchaRepository {

  @Override
  public <C extends ValidateCode> void save(String requestId, C code) {
    // TODO
  }

  @Override
  public String get(String requestId) {
    // TODO
    return null;
  }
}