Java实现Base64格式验证码

Java实现Base64格式验证码

  实现登录验证码一般分为两种方式:前端实现和后端实现。前端实现由于安全性考虑,就不采用那种方式了。本文主要讲述如何以后端方式生成验证码供前端调用并加以验证。

一、创建验证码服务

/**
 * @description: VerifyCodeService
 * @author: zero
 * @date: 2021/7/1 9:39
 */
@Service
@Slf4j
public class CaptchaService {
    /**
     * 宋体、新宋体、黑体、楷体、隶书
     */
    private static final String[] FONT_TYPES = { "\u5b8b\u4f53", "\u65b0\u5b8b\u4f53",
            "\u9ed1\u4f53", "\u6977\u4f53", "\u96b6\u4e66" };

    private static final int VALIDATE_CODE_LENGTH = 4;

    /**
     * 设置背景颜色及大小,干扰线
     *
     * @param graphics graphics
     * @param width width
     * @param height height
     */
    private static void fillBackground(Graphics graphics, int width, int height) {
        // 填充背景
        graphics.setColor(Color.WHITE);
        //设置矩形坐标x y 为0
        graphics.fillRect(0, 0, width, height);

        // 加入干扰线条
        for (int i = 0; i < 8; i++) {
            //设置随机颜色算法参数
            graphics.setColor(RandomUtil.randomColor(40, 150));
            Random random = new Random();
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            graphics.drawLine(x, y, x1, y1);
        }
    }

    /**
     * 生成随机字符
     * @param width width
     * @param height height
     * @param os os
     * @return String
     * @throws IOException IOException
     */
    public String generate(int width, int height, OutputStream os) throws IOException {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.getGraphics();
        fillBackground(graphics, width, height);
        String randomStr = RandomUtil.randomString(VALIDATE_CODE_LENGTH);
        createCharacter(graphics, randomStr);
        graphics.dispose();
        //设置JPEG格式
        ImageIO.write(image, "JPEG", os);
        return randomStr;
    }

    /**
     * 验证码生成
     *
     * @param width width
     * @param height height
     * @return VerifyCode
     */
    public Captcha generate(int width, int height) {
        Captcha captcha = null;
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            String code = generate(width, height, baos);
            captcha = new Captcha();
            captcha.setCode(code);
            captcha.setImgBytes(baos.toByteArray());
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return captcha;
    }

    /**
     * 设置字符颜色大小
     *
     * @param g g
     * @param randomStr randomStr
     */
    private void createCharacter(Graphics g, String randomStr) {
        char[] charArray = randomStr.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            //设置RGB颜色算法参数
            g.setColor(new Color(50 + RandomUtil.nextInt(100),
                    50 + RandomUtil.nextInt(100), 50 + RandomUtil.nextInt(100)));
            //设置字体大小,类型
            g.setFont(new Font(FONT_TYPES[RandomUtil.nextInt(FONT_TYPES.length)], Font.BOLD, 26));
            //设置x y 坐标
            g.drawString(String.valueOf(charArray[i]), 15 * i + 5, 19 + RandomUtil.nextInt(8));
        }
    }
}

二、创建验证码接口

/**
 * @description: LoginController
 * @author: zero
 * @date: 2021/4/19 15:45
 */
@Slf4j
@RestController
public class LoginController extends BaseController {
    @Autowired
    private LoginService loginService;

    @Autowired
    private CaptchaService captchaService;

    /**
     * 登录接口
     * @param username username
     * @param password password
     * @param verifyCode verifyCode
     * @return CommonResult<Object>
     */
    @Log(module = "权限管理", description = "登录")
    @GetMapping("/login")
    public CommonResult<Object> login(String username, String password, String verifyCode, HttpServletRequest request) {
        // 先校验验证码是否正确
        String captcha = request.getSession().getAttribute("captcha").toString();
        if (StringUtils.equalsIgnoreCase(verifyCode,captcha)) {
            Map<String, String> data = new HashMap<>(1);
            String ipAddr = IpUtil.getIpAddr(request);
            String token = loginService.login(username, password, ipAddr);
            if (StringUtils.isEmpty(token)) {
                return fail("login failed.");
            }
            data.put("token", token);
            return success(data);
        } else {
            return fail("验证码错误!");
        }
    }

    @GetMapping("/captcha")
    public CommonResult<Object> getVerifyCode(int width, int height, HttpServletRequest request, HttpServletResponse response) {
        Captcha captcha = captchaService.generate(width, height);
        String code = captcha.getCode();
        Base64.Encoder encoder = Base64.getEncoder();
        String image =  encoder.encodeToString(captcha.getImgBytes());
        log.info("获取到的验证码为:{}", code);
        String result = "data:image/png;base64,"+image;
        request.getSession().setAttribute("captcha", code);
        return success(result);
    }
}

三、前端验证

<template>
<el-form-item prop="verifyCode" class="form-item-bg verifyCodeItem">
  <!-- <span class="svg-container">
    <svg-icon icon-class="user" />
  </span> -->
  <el-input
    v-model="loginForm.verifyCode"
    placeholder="输入验证码"
    type="text"
  />
  <img :src="captchaUrl" @click="getCaptcha" style="height:25px;margin-right:5px;  "  />
</el-form-item>
</template>
<script>
export default {
methods: {
    getCaptcha(){
      captcha({
        width:80,
        height:26
      }).then( res =>{
        if(res.code==='0'){
          this.captchaUrl = res.data
        }
      })
    }
}
}
</script>

效果如下:
在这里插入图片描述

文中后端代码核心参考:https://blog.csdn.net/pengjunlee/article/details/102896114

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zerooooooooooooooooo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值