目录
1. 生成验证码
2. 将本地验证码发布成 URL
3. 后端返回验证码的 URL 给前端
4. 前端将用户输入的验证码传给后端
5. 后端验证验证码
1. 生成验证码
使用hutool 工具生成验证码.
1.1 添加 hutool 验证码依赖
<!-- 验证码 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
1.2 创建验证码的控制器
@RestController
public class CaptchaController {
@Value("${imagepath}")
private String imagepath; // 验证码的本地路径
@RequestMapping("/getcaptcha")
public Object getCaptcha1(){
// 1.生成验证码到本地
//定义图形验证码的长和宽 (这个验证码的大小需要和自己前端的验证码的大小匹配)
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(128, 50);
String uuid = UUID.randomUUID().toString().replace("-","");
// 图形验证码写出,可以写出到文件,也可以写出到流
lineCaptcha.write(imagepath + uuid + ".png");
return AjaxResult.success(imagepath+uuid+".png");
}
}
application.propertities 中添加验证码保存路径 (末尾一定要带斜杆)
# 验证码保存路径
imagepath=D:/image/
【注意】
- 如果项目中配置了拦截器, 那么一定要记得再拦截规则中给验证码的路由放行!!
- 使用 UUID 每次生成不同地址的验证码
1.3 前端关键代码
<div class="row" style="margin-bottom: 20px;">
<span>验证码</span>
<input id="checkCode" style="width: 66px;">
<img onclick="loadCode()" id="codeimg" src=""
style="height: 50px;width: 128px;">
</div>
浏览器直接访问接口 : 127.0.0.1:8080/getcaptcha
再查看本地路径也确实生成了对应的验证码 :
2. 将本地验证码发布成 URL
2.1 配置映射图片路径
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Value("${imagepath}")
private String imagepath;
/**
* 映射图片路径
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/image/**")
.addResourceLocations("file:" + imagepath + "/");
}
}
使用网络路径 /image/** 映射到本地验证码路径, 注意 "file:" + imagepath + "/" 这最后可能要加上一个斜杆才能生效. (因人而异)
2.2 使用映射后的网络路径访问验证码
浏览器输入: 127.0.0.1:8080/image/b1306474838b4b0e9f8a6ac7606567cb.png
成功访问到了!!
3. 后端返回验证码的 URL 给前端
后端不仅要返回验证码给前端, 还需要返回一个 "验证码的 key" 给前端.
后端返回验证码的 URL 给前端可以理解, 前端需要展示给用户看;
那么验证码的 key 是啥呢 ???
后端需要将验证码存储 redis, 因为验证码在某一时间内可以生成很多, 而用户输入的正确与否, 需要在后端进行判断, 后端进行判断时, 就得把生成的验证码存储 redis (快), 而存储 redis 我们可以借着前面的 UUID , 把 UUID 作为 key, 验证码作为 value 去存储. 然后再将 key 去传给前端, 前端就可以带着输入的验证码和 key 一起传给后端, 后端就可以拿着 key 去查 redis 得到一个验证码, 然后与前端传过来的作比较即可.
3.1 完善后端 CaptchaController.java 代码
@RestController
public class CaptchaController {
@Value("${imagepath}")
private String imagepath; // 验证码的本地路径
@Resource
private RedisTemplate redisTemplate; // 将存储验证码的 key - uuid
@RequestMapping("/getcaptcha")
public Object getCaptcha(){
// 1.生成验证码到本地
//定义图形验证码的长和宽 (这个验证码的大小需要和自己前端的验证码的大小匹配)
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(128, 50);
String uuid = UUID.randomUUID().toString().replace("-","");
// 图形验证码写出,可以写出到文件,也可以写出到流
lineCaptcha.write(imagepath+uuid+".png");
// 验证码的网络地址
String url = "/image/"+uuid+".png";
// 将验证码存储到 redis
redisTemplate.opsForValue().set(uuid,lineCaptcha.getCode());
HashMap<String,String> result = new HashMap<>();
result.put("codeurl",url);
result.put("codekey",uuid);
return AjaxResult.success(result);
}
}
4. 前端将用户输入的验证码传给后端
4.1 前端加载验证码
<script>
// 验证码key
var codeKey = "";
// 获取并显示验证码
function loadCode() {
jQuery.ajax({
url: "/getcaptcha",
type: "GET",
data: {},
success: function (res) {
if (res.code = 200 && res.data != null && res.data != "") {
// 获取验证码成功
codeKey = res.data.codekey;
jQuery("#codeimg").attr("src", res.data.codeurl);
}
}
});
}
loadCode();
</script>
效果图
4.2 前端将验证码和 key 传给后端
jQuery.ajax({
url:"/user/reg",
type:"post",
data:{
username:username.val(),
password:password.val(),
checkCode:checkCode.val(),
codeKey:codeKey
},
success:function(body) {
if(body.code==200 && body.data!=null) {
alert("恭喜,注册成功!");
if(confirm("是否要去登录页面 ?")) {
location.href = "login.html";
}
} else if(body.code == -1) {
alert("抱歉, 注册失败, 请重新注册! " + body.msg);
} else {
alert("该用户名已被使用, 请重新输入!");
}
}
});
5. 后端验证验证码
5.1 注册功能中验证验证码
@RequestMapping("/reg")
public Object reg(UserInfoVo userInfoVo) {
// 1. 非空效验
// 省去具体代码....
// 2.检查验证码是否正确
String redisCodeValue =
(String) redisTemplate.opsForValue().get(userInfoVo.getCodeKey());
if(!StringUtils.hasLength(redisCodeValue) ||
!redisCodeValue.equals(userInfoVo.getCheckCode())) {
// 验证码不正确
return AjaxResult.fail(-1, "验证码错误!");
}
// .....
// .... 其他业务逻辑
return AjaxResult.success(result);
}
登录功能的后端验证验证码其实是一样的方法, 照猫画虎即可~
此处的验证码功能是针对之前的博客 - SSM - 博客系统 来做的一个扩展功能, 有兴趣的可以去实现一下~~