一次性验证码的生成及校验——Session的应用


在这里插入图片描述
为什么需要一次性验证码?
一次性验证码即验证码即表单只能提交一次,第二次提交表单,原来的验证码失效,将无法提交表单,这样做可以减轻服务器压力,也可以防止表单的重复提交
怎样确保验证码只能使用一次?
用户输入的验证码通过前台表单或者是js传到后台,同时在session中拿到生成的验证码(生成一次验证码就存入session中),进行比对,无论比对结果如何,都将销毁session中的验证码
如何实现点击图片切换验证码
在这里插入图片描述
在这里插入图片描述
改变图片的src,src等于controller的地址,绑定onclick事件,点击图片触发
但是浏览器会缓存请求和响应,如果第二次请求的地址和第一次相同,浏览器就不会请求服务器,直接响应上次结果
解决方案:在请求路径上添加随机参数(后端不接收参数),确保每次请求地址不同
在这里插入图片描述

前端html

<div class="row">
	<div class="col-xs-7">
		<div class="form-group has-feedback">
			<label for="code">验证码</label>
			<div class="input-group">
				<span class="input-group-addon"><span class="glyphicon glyphicon-qrcode"></span></span>
				<input id="code" name="code" class="form-control" placeholder="请输入验证码" maxlength="6" type="text">
				<img src="/CA/user/code" onclick="changeImg()" id="picc">
			</div>
			<span style="color:red;display: none;" class="tips"></span>
			<span style="display: none;" class="glyphicon glyphicon-remove form-control-feedback"></span>
			<span style="display: none;" class="glyphicon glyphicon-ok form-control-feedback"></span>
		</div>
	</div>
</div>

前端js——点击切换图片、校验验证码

function changeImg(){
	var img = document.getElementById("picc");
	img.src="/CA/user/code?time="+new Date().getTime();
}
//自定义校验,验证码是否正确
		$.validator.addMethod("yzm",function(value,ele,params){
			var result = '';
			console.log(value);
			console.log(typeof(value));
			$.ajax({
					type:"get",
					url:"/CA/user/checkCode?code="+value,
					async:false,//关闭ajax的异步调用,改为同步
					success:function(data){
						console.log(data);
						result = data;
						console.log(result);
					}
				});
			console.log(result);
			if(result=="OK"){
				console.log(123);
				return true;
			}
			return false;
		},"验证码错误");

服务器端代码

生成验证码

@RequestMapping("/user/code")
	public void newCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 1 高和宽
		int height = 30;
		int width = 100;
		String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
		Random random = new Random();
		// 2 创建一个图片
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 3 获得画板
		Graphics g = image.getGraphics();
		// 4 填充一个矩形
		// * 设置颜色
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, width, height);
		g.setColor(Color.WHITE);
		g.fillRect(1, 1, width - 2, height - 2);
		// * 设置字体
		g.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 25));
		// 5 写随机字
		String msg = "";// 用来拼接验证码,以传递到其他servlet
		for (int i = 0; i < 4; i++) {
			// 设置颜色--随机数
			g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
			// 获得随机字
			int index = random.nextInt(data.length());
			String str = data.substring(index, index + 1);
			// 拼接随机数(生成验证码)
			msg += str;
			// 写入
			g.drawString(str, width / 6 * (i + 1), 20);
		}
		// 把生成的验证码放入session域
		System.out.println(msg);
		//request.getSession().setAttribute("msg", msg);
		HttpSession session = request.getSession();
		session.setAttribute("msg", msg);
		// 6 干扰线
		for (int i = 0; i < 3; i++) {
			// 设置颜色--随机数
			g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
			// 随机绘制先
			g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
			// 随机点
			g.drawOval(random.nextInt(width), random.nextInt(height), 2, 2);
		}
		// end 将图片响应给浏览器
		ImageIO.write(image, "jpg", response.getOutputStream());
	}

校验验证码

验证码比对,用户提交的验证码和保存在session中的验证码进行对比,对比完立即销毁session中的验证码,确保一次性验证码

@RequestMapping("/user/checkCode")
	@ResponseBody
	public String checkCode(@RequestParam String code,HttpServletRequest request, HttpServletResponse response) {
		System.out.println(code);
		String msg = (String) request.getSession().getAttribute("msg");
		System.out.println(msg);
		//request.getSession().removeAttribute("msg");//销毁验证码的session,一次性验证码
		if (code.equalsIgnoreCase(msg)) {//忽略大小写
			request.getSession().removeAttribute("msg");
			return "OK";
		}else {
			request.getSession().removeAttribute("msg");
			return "FAIL";
		}
		
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值