• 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码,其原理与利用Session防止表单重复提交的原理基本一样,只是将表单标识号变成了验证码的形式,并且要求用户将提示的验证码手工填写进一个表单字段中,而不是通过表单的隐藏字段自动回传给服务器。
  • 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
  • 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。

表单页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${MessageIfo}
<form action="<%=request.getContextPath()%>/checkCodeServlet" method="post">
Username:<input type="text" name="username"/>
<br><br>
验证码:<input type="text" name="checkCode"/>
<br><br>
<img src="<%=request.getContextPath()%>/validateColorServlet">
<br><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>

生成验证码的Servlet

package yang.mybatis.servlet.checkCode;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random; import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by yangshijing on 2017/11/23 0023.
*/
public class ValidateColorServlet extends HttpServlet { public static final String CHECK_CODE_KEY = "CHECK_CODE_KEY"; private static final long serialVersionUID = 1L; //设置验证图片的宽度, 高度, 验证码的个数
private int width = 152;
private int height = 40;
private int codeCount = 4; //验证码字体的高度
private int fontHeight = 4; //验证码中的单个字符基线. 即:验证码中的单个字符位于验证码图形左上角的 (codeX, codeY) 位置处
private int codeX = 0;
private int codeY = 0; //验证码由哪些字符组成
char [] codeSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz23456789".toCharArray(); //初始化验证码图形属性
public void init(){
fontHeight = height - 2;
codeX = width / (codeCount + 2);
codeY = height - 4;
} public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//定义一个类型为 BufferedImage.TYPE_INT_BGR 类型的图像缓存
BufferedImage buffImg = null;
buffImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); //在 buffImg 中创建一个 Graphics2D 图像
Graphics2D graphics = null;
graphics = buffImg.createGraphics(); //设置一个颜色, 使 Graphics2D 对象的后续图形使用这个颜色
graphics.setColor(Color.WHITE); //填充一个指定的矩形: x - 要填充矩形的 x 坐标; y - 要填充矩形的 y 坐标; width - 要填充矩形的宽度; height - 要填充矩形的高度
graphics.fillRect(0, 0, width, height); //创建一个 Font 对象: name - 字体名称; style - Font 的样式常量; size - Font 的点大小
Font font = null;
font = new Font("", Font.BOLD, fontHeight);
//使 Graphics2D 对象的后续图形使用此字体
graphics.setFont(font); graphics.setColor(Color.BLACK); //绘制指定矩形的边框, 绘制出的矩形将比构件宽一个也高一个像素
graphics.drawRect(0, 0, width - 1, height - 1); //随机产生 15 条干扰线, 使图像中的认证码不易被其它程序探测到
Random random = null;
random = new Random();
graphics.setColor(Color.GREEN);
for(int i = 0; i < 15; i++){
int x = random.nextInt(width);
int y = random.nextInt(height);
int x1 = random.nextInt(20);
int y1 = random.nextInt(20);
graphics.drawLine(x, y, x + x1, y + y1);
} //创建 randomCode 对象, 用于保存随机产生的验证码, 以便用户登录后进行验证
StringBuffer randomCode;
randomCode = new StringBuffer(); for(int i = 0; i < codeCount; i++){
//得到随机产生的验证码数字
String strRand = null;
strRand = String.valueOf(codeSequence[random.nextInt(36)]); //把正在产生的随机字符放入到 StringBuffer 中
randomCode.append(strRand); //用随机产生的颜色将验证码绘制到图像中
graphics.setColor(Color.BLUE);
graphics.drawString(strRand, (i + 1)* codeX, codeY);
} //再把存放有所有随机字符的 StringBuffer 对应的字符串放入到 HttpSession 中
request.getSession().setAttribute(CHECK_CODE_KEY, randomCode.toString()); //禁止图像缓存
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0); //将图像输出到输出流中
ServletOutputStream sos = null;
sos = response.getOutputStream();
ImageIO.write(buffImg, "jpeg", sos);
sos.close();
}
}

表单处理Servlet

package yang.mybatis.servlet.checkCode;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; /**
* Created by yangshijing on 2017/11/23 0023.
*/
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String check_code_key = (String)session.getAttribute("CHECK_CODE_KEY");
String checkCode = request.getParameter("checkCode");
//不区分大小写
if(check_code_key != null && !check_code_key.trim().equals("")){
check_code_key = check_code_key.toLowerCase();
}
if (checkCode != null && !checkCode.trim().equals("")){
checkCode = checkCode.toLowerCase();
}
//验证码为NULL或者两者不等,重定向到信息提示页面
if(check_code_key == null || checkCode == null && !check_code_key.equals(checkCode)){
request.getSession().setAttribute("MessageIfo","验证不一致");
response.sendRedirect(request.getContextPath()+"/jsp/checkCode/index.jsp");
return;
}
//如果两个验证码一致,处理该表单请求,并移除sesssion域中的属性值
session.removeAttribute("CHECK_CODE_KEY");
response.sendRedirect(request.getContextPath()+"/jsp/token/success.jsp");
}
}

简单的Session案例 —— 一次性验证码的更多相关文章

  1. 使用session实现一次性验证码

    在登录页面和各种页面,会看到有验证码输入,这样做的目的是为了防止密码猜测工具破解密码,保护了用户密码安全,验证码只能使用一次,这样就给密码猜测工具带来了很大的困难,基本上阻断了密码猜测工具的使用. 可 ...

  2. JavaWeb 使用Session实现一次性验证码

    表单 <form action="loginServlet" method="post"> 请输入验证码:<input type=" ...

  3. session案例之验证码

    一.需求分析 其中,一张图片就是一个单独的请求: 一个验证验证码的Servlet,还有一个验证用户名和密码的Servlet,两次都可能有错误信息返回到前端页面,所以前面页面要从request域中获取返 ...

  4. JAVA实用案例之验证码开发

    验证码在很多地方都会遇到,实现的方法和形式也有很多,主要的目的就是为了安全,防止一些恶意的攻击等.说实话那么多年竟然没注意过这东西,原理很简单,贴出来给大家做个参考. 1.简单介绍 一般稍微有些经验的 ...

  5. Java Web(四) 一次性验证码的代码实现

    其实实现代码的逻辑非常简单,真的超级超级简单. 1.在登录页面上login.jsp将验证码图片使用标签<img src="xxx">将绘制验证码图片的url给它 2.在 ...

  6. web开发(四) 一次性验证码的代码实现

    在网上看见一篇不错的文章,写的详细. 以下内容引用那篇博文.转载于<http://www.cnblogs.com/whgk/p/6426072.html>,在此仅供学习参考之用. 其实实现 ...

  7. Python3+Dlib实现简单人脸识别案例

    Python3+Dlib实现简单人脸识别案例 写在前边 很早很早之前,当我还是一个傻了吧唧的专科生的时候,我就听说过人脸识别,听说过算法,听说过人工智能,并且也出生牛犊不怕虎般的学习过TensorFl ...

  8. Session中短信验证码设置有效时间

    Session中短信验证码设置有效时间 package com.mozq.boot.kuayu01.controller; import org.springframework.web.bind.an ...

  9. 使用Java实现简单的斗地主案例

    使用Java实现简单的斗地主案例 案例说明:使用Java实现简单的斗地主洗牌发牌的操作: 具体规则: 共有54张牌,顺序打乱: 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后留三张为底牌(地主牌) ...

随机推荐

  1. ubantu 虚拟机无法查看windows共享目录

    初学linux,安装好虚拟机,安装好ubantu系统,启动系统后无法查看windows共享目录. 原因是没有安装 vmware tools 教程地址:http://www.linuxidc.com/L ...

  2. Linux多网卡的时候执行机器Ip

    在Linux部署的时候,经常会有多网卡的情况出现,这时候项目又需要指定Ip.在这种情况下,要配置linux机子的host,指定里头要使用的ip地址,否则linux机子不知道去找哪个ip. 一.查看本机 ...

  3. 笔记:开源协议 Apache 2 和 GPL 兼容

    笔记:开源协议 Apache 2 和 GPL 兼容 Apache 2 和 GPL v3 兼容. GPL 分了很多版本,LGPL 为最宽松的 GPL,而 AGPL 为最严格的 GPL 协议. Linux ...

  4. (转)安装Android SDK时遇到Failed to rename directory

    安装Android SDK时遇到Failed to rename directory E:\Java\Android SDK\android-sdk_r06-windows\android-sdk-w ...

  5. zabbix 触发器 | count 函数

    摘要:确认多次zabbix监控中小编用的最多的是count的这函数,确认多次以减少了很多误告警,提高了运维效率.可以设置连续几次都异常才发出告警,这样一来,只要发出告警基本上就已经确定发生故障了.co ...

  6. Oracle记录(三) Scott用户的表结构

    在Oracle的学习之中,重点使用的是SQL语句,而所有的SQL语句都要在scott用户下完成,这个用户下一共有四张表,可以使用: SELECT * FROM tab; 查看所有的数据表的名称,如果现 ...

  7. mysql 统计sql

    1.按照月份统计数据 SELECT DATE_FORMAT(d.create_time,'%Y-%m') months,COUNT(id) AS scannum FROM detail d GROUP ...

  8. erlang分布式例子

    抄袭自 http://www.blogjava.net/killme2008/archive/2007/06/29/127099.html 简单的说,就是 主机上需要同时启用短节点名,或者长节点名 保 ...

  9. DSP SYS/BIOS开发

    https://blog.csdn.net/lg1259156776/article/details/80695318

  10. selenium新的定位方法,更简洁很方便

    亲测是可以的 self.driver.find_element('id','kw').send_keys(u"凯宾斯基")