验证码实现
验证码案例
学了Spring MVC ,配置 相关章节, 现可以尝试写一个前后端交互的验证码
文章目录
- 验证码案例
- 前言
- 一、验证码是什么?
- 二、需求
- 1.引入依赖
- 2.导入前端页面
- 3.约定前后段交互接口
- 三、代码解析
- Controller
- model
- application.xml
- 四丶结果
- 五丶总结
前言
提示:这里可以添加本文要记录的大概内容:
页面如下图所示
1.页面生成验证码
2.输入验证码,点击提交,验证用户输入验证码是否正确,正确则页面跳转
提示:以下是本篇文章正文内容,下面案例可供参考
一、验证码是什么?
验证码,是来区分用户是计算机还是人的公共全自动程序,可以防止:恶意破解密码,刷票,等有效防止某个黑客对特定用户进行暴力登录,这个问题必须只有人类才能解答,验证码花样百出,下面我们将采用扭曲干扰验证码来实现前后端交互的接口
二、需求
1.引入依赖
代码如下(示例):
<dependencies>
//SpingWeb 框架
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// lombok 自动生成
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
//test 测试方法
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
//验证码 相关的类 封装好了的 直接用
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.26</version>
</dependency>
</dependencies>
把这段代码加入pom.xml文件中即可,但是要把里面的注释删了 ,否则会出错
2.导入前端页面
代码如下(示例):
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>验证码</title>
<style>
#inputCaptcha {
height: 30px;
vertical-align: middle;
}
#verificationCodeImg{
vertical-align: middle;
}
#checkCaptcha{
height: 40px;
width: 100px;
}
</style>
</head>
<body>
<h1>输入验证码</h1>
<div id="confirm">
<input type="text" name="inputCaptcha" id="inputCaptcha">
<img id="verificationCodeImg" src="/captcha/getCaptcha" style="cursor: pointer;" title="看不清?换一张" />
<input type="button" value="提交" id="checkCaptcha">
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$("#verificationCodeImg").click(function(){
$(this).hide().attr('src', '/captcha/getCaptcha?dt=' + new Date().getTime()).fadeIn();
});
$("#checkCaptcha").click(function () {
$.ajax({
url:"/captcha/check",
type:"post",
data:{
captcha:$("#inputCaptcha").val()
},
success: function(result){
if(result==true){
location.href="/success.html"
}else{
alert("验证码错误");
}
}
})
});
});
</script>
</body>
</html>
success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>验证成功页</title>
</head>
<body>
<h1>验证成功</h1>
</body>
</html>
3.约定前后段交互接口
需求分析
后端需要提供两个服务
- 生成验证码,并返回验证码;
- 校验验证码是否正确;
接口定义
1.生成验证码
请求:
请求URL:/captcha/getCaptcha
响应:验证码图片内容
2.校验验证码是否正确
请求:
请求URL:/captcha/check
请求参数:captcha ,用户传过来的验证码
响应: true / false
三、代码解析
Controller
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
//注入配置 对象 , 一些常量从里面读取
@Autowired
private CaptchaProperties cp;
//易凤种 华为ms
private static long VALID_TIME_OUT = 60*1000;
@RequestMapping("/getCaptcha")
public void getCaptcha(HttpSession session, HttpServletResponse response) {
//生成验证码 ,并把验证码写入浏览器中
//定义图形验证码的长和宽
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(cp.getWidth(), cp.getHeight(), cp.getCodeCount(), cp.getCilceCount());
//打印验证码
String code = captcha.getCode();
System.out.println(code);
//验证码 , 当前时间 存入Session
session.setAttribute(cp.getSession().getCode(), code);
session.setAttribute(cp.getSession().getDate(), new Date());
try {
//把验证码写到浏览器中
captcha.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//校验验证码,获取生成的验证码 写给Session
@RequestMapping("/check")
public boolean check(String captcha,HttpSession session) {
//校验是否为空,防止equls空指针
if(!StringUtils.hasLength(captcha)){
return false;
}
//从Session中读取值
String code = (String) session.getAttribute(cp.getSession().getCode());
Date date = (Date) session.getAttribute(cp.getSession().getDate());
//校验获取验证码的时间 和 校验时间 的差值不能超过一分钟
if(date == null || (System.currentTimeMillis() - date.getTime()) > VALID_TIME_OUT){
return false;
}
return captcha.equalsIgnoreCase(code);
}
}
解析 :接口getCaptcha ,用来生成验证码(从hutool上面cv),那么如何将生成的验证码传给另一个接口呢 ? 设置Session,response是用来把验证码写入到文件/浏览器中的 ,前端用来改一下img中图片的src属性即可获取
Controller 从model中获取配置信息, 需要依赖注入 ,各种常量属性,和存储在Session中的“key
model
@Data
@Configuration
@ConfigurationProperties(prefix = "captcha")
//读取配置的信息
public class CaptchaProperties {
private Integer width;
private Integer height;
private Integer codeCount;
private Integer cilceCount;
private Session session;
@Data
public static class Session {
private String code;
private String date;
}
}
配置对象的接口 ,用来获取配置中的信息(对象) ,并封装成一个类,需要用到@configurationproperties(“prefix="对象名"”)并且设置对象中的属性,内部类
,注意使用内部类 一般要加上 public static 或者会出现错误 具体原因后续再说
@Data 是用来生成 get/set 方法的,来自于lombok依赖
application.xml
captcha:
width: 100
height: 40
codeCount: 4
circleCount: 40
Session:
key: SESSION_CAPTCHA_KEY
date: SESSION_CAPTCHA_DATE
配置相关信息,配置了验证码的相关属性,前后端交互时的Session , 使用 key - value 的形式
四丶结果
点击“提交”,跳转页面 成功!!
五丶总结
问题:
- HttpSErvletResponse 是什么 ? 为什么能写入到浏览器 ?
- 在验证代码时,在一个接口中把验证码传给Session ,另一个接口为什么能从Session中获取到?
- 在使用内部类时, 为什么 要设置 public ? 为什么 要用static才能运行?
- [ ]
注意:
- System.currentTimeMillis() 表示当前时间 ,类型为long , 单位为ms