分为前后端两个部分,先从后端开始:
首先要创建实体类,要包含验证码的key(我们需要用Key去获取存储在redis中对应的验证码的值)
@Data public class User { private int id; private String username; private String password; private String codekey; private String codevalue; private String email; private String role; private boolean state; public User() { } }
这里遇到过一个很有趣的小BUG,就是不要设置变量为CodeKey这样的大驼峰,或者说,变量的第一个字母一定不要大写,因为可能会导致@Data中的方法无法识别你的变量。
前端加载登录页面的时候,需要发送请求给后端,来获取验证码的信息,包括验证码图片的url,以及验证码的key。
@RestController public class VerificationCodeController { @Value("${imagepath}") private String imagepath; // 验证码的本地路径 @Resource private RedisTemplate redisTemplate; // 将存储验证码的 key - uuid @RequestMapping("/getcaptcha") public Object getCaptcha1(){ // 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()); HashMapres = new HashMap<>(); res.put("code",200); res.put("codeurl",url); res.put("codekey",uuid); String users_json = JSON.toJSONString(res); return users_json; } }
在application.properties文件中,需要配置你的图片存储的位置,加上下面这一行。
imagepath=D:/images/
接着创建controller,我这里的是登录请求。
@RestController public class LoginController { @Autowired UserDao userDao; @Resource private RedisTemplateredisTemplate; // 指定 RedisTemplate 的泛型类型为 @CrossOrigin @RequestMapping("/login") public String userLogin(@RequestBody User user) { // 1.检查验证码是否正确 String redisCodeValue = (String) redisTemplate.opsForValue().get(user.getCodekey()); if(!StringUtils.hasLength(redisCodeValue) || !redisCodeValue.equals(user.getCodevalue())) { // 验证码不正确 return "验证码错误!"; } //2.再判断登录信息 String str = "error"; int count = userDao.getUserByMassage(user.getUsername(), user.getPassword()); if (count > 0) { str = "ok"; } return str; } }
验证码
async loadCode() { const res = await this.$http.get("getcaptcha"); this.codeImg = "http://127.0.0.1:9000/" + res.data.codeurl; this.loginForm.codekey = res.data.codekey; },
login() { this.$refs.loginFormRef.validate(async (valid) => { if (!valid) return; // 调用get请求 const { data: res } = await this.$http.post("login", this.loginForm); if (res == "ok") { window.sessionStorage.setItem("flag", "ok"); // session 放置 this.$message.success("登陆成功!!!"); this.$router.push({ path: "/home" }); } else { this.$message.error("登录失败!!!"); } }); },
从逻辑顺序来讲,前端发送获取验证码请求,后端接收到之后,生成验证码图片,返回图片的信息(url,codeKey),前端拿到返回结果之后,可以通过url展示图片。
接着用户输入信息之后,发送登录请求,后端拿到验证码信息(用户输入的值和codeKey)之后,和存储在redis中的数据进行对比校验,相等的情况下,通过。
上一篇:IP证书是什么?怎么申请?