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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值