java生成图片验证码,前端回显

java生成图片验证码

使用场景:

  1. 获取手机、邮件验证码之前做一层检测是否是人为验证
  2. 登录、注册之前做一层检测是否是人工验证
  3. 频繁点击登录、注册接口做一层检测是否是人为验证

一、引入相关依赖

	<!-- 添加图形验证码依赖 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-captcha</artifactId>
            <version>5.8.6</version>
        </dependency>

  1. createCode 创建验证码,实现类需同时生成随机验证码字符串和验证码图片
  2. getCode 获取验证码的文字内容
  3. verify 验证验证码是否正确,建议忽略大小写
  4. write 将验证码写出到目标流中
  5. 而AbstractCaptcha为一个ICaptcha抽象实现类,此类实现了验证码文本生成、非大小写敏感的验证、写出到流和文件等方法,通过继承此抽象类只需实现createImage方法定义图形生成规则即可。

二、生成图形验证码(模拟场景发送手机验证码)

    /**
     * 获取图形验证码
     * @param response 请求
     * @param captchaCode 前端随机的编码用于验证图形验证码唯一标识
     * @return 返回验证码图片64位
     */
    @GetMapping("/createCaptcha")
    public ApiResult createCaptcha(HttpServletResponse response, @NotNull @RequestParam("captchaCode") String captchaCode)  {

        String phoneCode = CODE_PHONE_CAPTCHA + captchaCode;
        // 定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        logger.info("lineCaptcha.getCode(){}",lineCaptcha.getCode());
        // 获取的验证码值,缓存起来用于验证
        String code = lineCaptcha.getCode();
        // 获取图片64位字符串
        String imageBase64 = lineCaptcha.getImageBase64();
        Map<String, Object> data = Maps.newConcurrentMap();
        // 转成图片64位让前端显示
        data.put("imageBase64" , imageBase64);
        // 前端传参验证码唯一标识
        data.put("captchaCode", captchaCode);
        // 设置有效期30秒
        redisUtils.set(phoneCode , code, 30);
        return ApiResult.success("获取成功", data);
    }

    /**
     * 发送短信每个ip限制一天200个请求
     *
     * @param phone 手机号
     * @param captchaValue 验证码值
     * @param captchaCode 验证码编码
     */
    @ApiOperation(value = "发送短信", notes = "根据手机号发送通用短信")
    @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "String", paramType = "query", example = "15243686469")
    @PostMapping("/verificationCodeToPhone")
    public ApiResult sendPhoneMsg(HttpServletRequest request,@NotNull @RequestParam("phone") String phone, @NotNull @RequestParam("captchaValue") String captchaValue,
                                  @NotNull @RequestParam("captchaCode") String captchaCode) {
        String ipAddress = IpAdrressUtil.getIpAddress(request);
        if (redisUtils.hasKey(CODE_IPADDRESS + ipAddress)) {
            Integer ipAddressCount = Integer.valueOf(redisUtils.get(CODE_IPADDRESS + ipAddress).toString());
            if (ipAddressCount > 200) {
                return ApiResult.error("当前IP已被限制发送短信,请求过多,请第二天重试!", 500);
            }
            redisUtils.incr(CODE_IPADDRESS + ipAddress, 1);
        } else {
        	// 禁止24小时
            redisUtils.set(CODE_IPADDRESS + ipAddress, 1, 60 * 60 * 24);
        }
        // 验证手机格式
        if (isMobile(phone)) {
            if (!redisUtils.hasKey(CODE_PHONE_CAPTCHA + captchaCode)) {
                throw new RuntimeException("图形码验证失败,请先刷新图片验证码重新输入!");
            }
            String codePhone =  redisUtils.get(CODE_PHONE_CAPTCHA + captchaCode).toString();
            if (!StringUtils.equals(codePhone,captchaValue)) {
                throw new RuntimeException("图形码验证失败,请先刷新图片验证码重新输入!");
            }
            if (redisUtils.hasKey(CODE_PHONE + phone)) {
                throw new RuntimeException("获取验证码失败,请求频繁,稍后再试!!!");
            }
            String code = roundNum();
            SmsUtils.getInstance().sendSms(phone, code);
            redisUtils.set(CODE_PHONE + phone, code, 60);
            return success(BaseErrorEnum.SUCCESS_SEND_OK.getErrorMessage(), phone);
        }
        return error(BaseErrorEnum.ERR_PHONE_FORMAT.getErrorMessage());
    }
        /**
     * 验证是否为一个手机号
     *
     * @param mobiles
     * @return
     */
    private boolean isMobile(String mobiles) {
        String telRegex = "[1][3456789]\\d{9}";
        // "[1]"代表第1位为数字1,"[3578]"代表第二位可以为3-9中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
        if (TextUtils.isEmpty(mobiles)) {
            return false;
        } else {

            return mobiles.matches(telRegex);
        }
    }

三、前端转为图片验证码

  1. JS代码,调用接口
			/**
			 * 获取图形验证码
			 */
			createCaptchaCode(){
				var captchaCode = this.uuid();
				var params = {
					captchaCode: captchaCode
				}
				this.captchaCode = captchaCode;
				getCreateCaptcha(params, data => {
					if (data && data.success){
						var datas = data.attributes;
						this.imgCodeObj.codeImg = datas.imageBase64;
						this.imgCodeObj.codeId = datas.captchaCode;
						console.log("data",data)
					}
					
				});
				console.log("this.captchaCode",this.captchaCode)
			},
			uuid() {
				return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
					var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
					return v.toString(16);
				});
			},
  1. vue代码(最主要这段::src=“‘data:image/png;base64,’ + imgCodeObj.codeImg”)
   							<div class="input-group mar-btm" v-show="isPhone">
   								<input :focus="inputFocus.codeFocus" v-model="captchaValue" id="captchaValue"
   									@keyup.enter="submit" autocomplete="off" class="form-control "
   									placeholder="图形验证码" style=" width: 250px; height: 50px;"/>
   									<span class="input-group-btn" >
   										<img
   										@click="createCaptchaCode"
   										style="margin-top: -30px; width: 140px; height: 50px;"
   										:src="'data:image/png;base64,' + imgCodeObj.codeImg"
   										/>
   									</span>
   							</div>

四、结果展示

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值