Web项目图形验证码登入功能完整实现

1、pom.xml文件引入Maven依赖

  <!--图片验证码-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-captcha</artifactId>
            <version>5.8.26</version>
        </dependency>

2、写一个工具类,里面存一些图形验证码需要的常量

/**
 * 图形验证码配置类
 */
@Configuration
public class ImageCode {
    /**
     * 图形验证码宽度
     */
    public static final Integer CAPTCHA_WIDTH = 100;
    /**
     * 图形验证码高度
     */
    public static final Integer CAPTCHA_HEIGHT = 40;
    /**
     *设置一个60秒的常量
     */
    public static final long EXPIRATION_TIME = 60 * 1000;
    /**
     * 验证码值
     */
    public static final String CAPTCHA_KEY = "captcha";
    /**
     * 验证码时间
     */
    public static final String CAPTCHA_DATE = "date";
}

3.编写获取图形验证码的get请求controller

注意:我这里设置响应给前端的数据类型是  response.setContentType("image/jpeg");

//生成图形验证码
    @GetMapping("/image")
    public Result imageCode(HttpSession session, HttpServletResponse response) {
        // 定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(ImageCode.CAPTCHA_WIDTH, ImageCode.CAPTCHA_HEIGHT);
        try {
            //图形验证码字符输出流到,一个向客户端返回的一个字节输出流对象
            lineCaptcha.write(response.getOutputStream());
            //设置格式,返回数据类型格式
            response.setContentType("image/jpeg");
            //禁用缓存
            response.setHeader("Pragma", "No-cache");
            // 将生成的验证码 和 验证码生成时间 存储到session中
            session.setAttribute(ImageCode.CAPTCHA_KEY, lineCaptcha.getCode());
            session.setAttribute(ImageCode.CAPTCHA_DATE, new Date());
            // 关闭字节输出流
            response.getOutputStream().close();
            //把这个给输出流对象返回到客户端
            return Result.success("200","获取图形验证码成功",response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

4.编写登入校验,和验证码校验post请求的controller,里面接收一个登入类型参数,并拿到HttpServletRequest,HttpServletRequest能抓取到该请求的全部信息。

LoginParm的实体类:

@Data
public class LoginParm {
    //用户名
    private String userName;
    //密码
    private String password;
    //验证码
    private String code;
}
//登录
    @PostMapping("/login")
    public Result login(@RequestBody LoginParm parm, HttpServletRequest request) {
        //获取session里面的code验证码
        HttpSession session = request.getSession();
        String code = (String) session.getAttribute("code");
        //获取前端传递过来的验证码
        String codeParm = parm.getCode();
        //判断验证码是否为空
        if (!StringUtils.hasLength(codeParm)) {
            return Result.error("504", "验证码为空");
        }
        // 获取存储的验证码和生成时间
        String imageCode = (String) session.getAttribute(ImageCode.CAPTCHA_KEY);
        //获取验证码的创建时间
        Date createTime = (Date) session.getAttribute(ImageCode.CAPTCHA_DATE);
        // 判断验证码是否正确(验证码一般忽略大小写)
        if (!codeParm.equalsIgnoreCase(imageCode)) {
            //判断验证码是否过时
            if (createTime == null || System.currentTimeMillis() - createTime.getTime() > ImageCode.EXPIRATION_TIME) {
                return Result.error("504","验证码失效");
            }
            return Result.error("504", "验证码错误");
        }
        //验证用户信息
        QueryWrapper<SysUser> query = new QueryWrapper<>();
        query.lambda().eq(SysUser::getUserName, parm.getUserName())
                //.eq(SysUser::getPassword, parm.getPassword());
                .eq(SysUser::getPassword, DigestUtils.md5DigestAsHex(parm.getPassword().getBytes()));
        SysUser user = sysUserService.getOne(query);
        //对比数据库  查询数据为null时
        if (user == null) {
            return Result.error("504", "用户名或者密码错误!");
        }
        //用户状态为  0表示禁用   1表示启用
        if (user.getStatus().equals("0")) {
            return Result.error("504", "账户被停用,请联系管理员!");
        }
        //返回封装好的登录信息  给客户端返回userId和nickName
        LoginVo vo = new LoginVo();
        vo.setUserId(user.getUserId());
        vo.setNickName(user.getNickName());
        return Result.success("登录成功", vo);
    }

5、前端使用axios发送请求,需要 npm i axios。

前端的响应拦截器,响应头默认以JSON格式数据解析

重点:在响应拦截器要设置对应的响应头类型,才能保证接收到该图形文件,不然会乱码。

拿到这个文件把图片路径解析出来并返回。

 if (response.headers["content-type"] === "image/jpeg") {
      // 处理图片数据
      let imageURL = URL.createObjectURL(
        new Blob([response.data], { type: "image/jpeg" })
      );
  
      return imageURL;
    }

6、重点:发送请求时一定要指定服务器响应的数据类型 responseType:'arraybuffer'

从服务器获取二进制文件(如图像、视频、音频等)时,使用 responseType: 'arraybuffer' 可以直接获取文件的二进制数据,而不是文本数据导致乱码。

//验证码
export const imageApi = () => request.get("/sysUser/image",{
    responseType:'arraybuffer'
});

7.获取验证码的成功案例

//验证码
const imgsrc = ref('')
//获取验证码
const getImg = async () => {
    let res = await imageApi() as any
        imgsrc.value = res
        console.log(res);   
}

每点击一次就发一次请求,切换验证码

 <img @click="getImg" class="image" :src="imgsrc" />

 参考网址:概述 | Hutool

### 如何在 JMeter 中实现带图片验证码登录测试 #### 准备工作 为了成功执行带有图片验证码登录测试,在准备阶段需确保安装并配置好必要的工具和库文件。具体来说,需要将`VcodeExtractor.jar`插件放置于JMeter的指定目录内以便调用其功能来解析图像验证码[^1]。 #### 获取验证码 对于Web应用而言,通常会提供专门用于获取图形验证码的服务接口。利用HTTP请求采样器模拟浏览器行为向服务器发起GET请求以下载该动态生成的验证码图片资源。由于这类验证码往往采用一次性机制设计,即每次刷新都会改变内容,因此建议在同一事务控制器下先后顺序安排两个子级取样器——先抓取最新产生的验证码再提交表单数据完成身份验证过程[^2]。 #### 图像处理与字符识别 考虑到直接操作二进制流较为复杂,可以借助第三方OCR光学字符识别技术辅助提取有效信息。上述提到过的自定义组件能够帮助简化这一步骤的操作流程,它内部集成了多种算法模型支持不同风格类型的码型转换任务。值得注意的是,实际项目环境中可能遇到各种干扰因素影响最终准确性,比如背景噪声、字体变形扭曲等问题都需要提前做好预案措施加以应对[^3]。 #### 构建参数化脚本 构建合理的变量映射关系是自动化测试框架的核心要素之一。这里可以通过正则表达式抽取器或者JSON路径断言等方式捕获前序步骤返回的结果作为后续环节所需传递的关键参数值。例如设置名为`${captcha}`的属性存储经由插件解密后的字符串序列供下一步POST方法携带使用[^4]。 ```java // 示例代码片段展示如何定义BeanShell预处理器读取外部文件加载至内存中 import java.io.BufferedReader; import java.nio.file.Files; import java.nio.file.Paths; String filePath = "path/to/captcha/image.png"; BufferedReader reader = Files.newBufferedReader(Paths.get(filePath)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } vars.put("imageData",sb.toString()); reader.close(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值