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