只需几步就可以生成动态随机的验证码,最终效果如下图:

一 前台显示页面login.jsp

其中验证码显示的是一张图片,链接指向的是生成验证码的servlet,同时点击图片后触发changeImg()这个js函数,使其动态生成一个新的验证码,这个函数中的参数t=Math.random()并不会参与验证码的生成,它的作用仅仅只是表示每次提交的并不是同一个请求,需要单独处理,完整的login.jsp代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<base href="<%=basePath%>">
<%@ include file="head.txt"%>
<script type="text/javascript">//刷新验证码function changeImg(){document.getElementById("validateCodeImg").src="helpDrawValidateCode?t=" + Math.random();}
</script>
</head>
<body><font size=3><center><form action="helpLogin" name="" method="post"><table><tr><th>请您登陆:</th></tr><tr><td align=left>会员名称:</td><td><input type=text name="id"></td></tr><tr><td align=left>输入密码:</td><td><input type=password name="password"></td></tr>               </table>  <br>验证码:<input type="text" name="validateCode" style="width:50px"><img alt="看不清?换一张" src="helpDrawValidateCode" id="validateCodeImg" οnclick="changeImg()">                            <br><input type="submit" value="提交"></form></center></font>
</body>
</html>

二 修改web.xml

  新增一个节点,代码如下:

<!-- 验证码绘制 --><servlet><servlet-name>drawValidateCode</servlet-name><servlet-class>com.zifangsky.OnlineFriend.servlet.member.HandleDrawValidateCode</servlet-class></servlet><servlet-mapping><servlet-name>drawValidateCode</servlet-name><url-pattern>/helpDrawValidateCode</url-pattern></servlet-mapping>

三 后台的servlet文件HandleDrawValidateCode.java

这个文件主要负责处理前台请求,并返回生成的验证码图片,同时将图片上的随机字符存入session中,以供登录时进行验证,HandleDrawValidateCode.java完整代码如下:

package com.zifangsky.OnlineFriend.servlet.member;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.p_w_picpath.BufferedImage;
import java.io.IOException;
import java.util.Random;import javax.p_w_picpathio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** 生成随机图片用做验证码* */
public class HandleDrawValidateCode extends HttpServlet{private static final long serialVersionUID = 1L;private static final int WIDTH = 120;  //图片宽度private static final int HEIGHT = 30;  //图片高度public void init(ServletConfig config) throws ServletException{super.init(config);}public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");HttpSession session = request.getSession(true);//创建一张图片BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);//得到图片Graphics graphics = bufferedImage.getGraphics();//设置图片背景色setBackGround(graphics);//设置图片边框setBordor(graphics);//在图片上画干扰线,用了4种颜色,共20条线条drawRandomLine(graphics,Color.GREEN);drawRandomLine(graphics,new Color(246,255,145));drawRandomLine(graphics,new Color(225,174,252));drawRandomLine(graphics,new Color(120,202,254));//在图片上写随机字符,并记录生成的序列String randomText = drawRandomText((Graphics2D) graphics);//将生成的字符存入session中session.setAttribute("checkcode", randomText);//设置响应头通知浏览器以图片的形式打开response.setContentType("p_w_picpath/jpeg");//设置响应头控制浏览器不要缓存response.setDateHeader("expries", -1);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");//将图片写给浏览器ImageIO.write(bufferedImage, "jpg", response.getOutputStream());}/*** 设置图片背景色* */private void setBackGround(Graphics graphics) {graphics.setColor(Color.WHITE);graphics.fillRect(0, 0, WIDTH, HEIGHT);}/*** 设置图片边框* */private void setBordor(Graphics graphics) {graphics.setColor(Color.BLUE);graphics.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);}/*** 在图片上画干扰线* */private void drawRandomLine(Graphics graphics,Color color) {graphics.setColor(color);//设置线条个数并画线for(int i = 0;i < 5;i++){int x1 = new Random().nextInt(WIDTH);int x2 = new Random().nextInt(WIDTH);int y1 = new Random().nextInt(HEIGHT);int y2 = new Random().nextInt(HEIGHT);graphics.drawLine(x1, y1, x2, y2);}}/*** 在图片上写随机字符,数字和字母的组合* @param length 字符串的长度* * @return 返回生成的字符串序列* */private String drawRandomText(Graphics2D graphics) {graphics.setColor(Color.RED);graphics.setFont(new Font("宋体", Font.BOLD, 20));//数字和字母的组合String baseNumLetter = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";StringBuffer sBuffer = new StringBuffer();int x = 5;  //旋转原点的 x 坐标String ch = "";Random random = new Random();for(int i = 0;i < 4;i++){//设置字体旋转角度int degree = random.nextInt() % 30;  //角度小于30度int dot = random.nextInt(baseNumLetter.length());ch = baseNumLetter.charAt(dot) + ""; sBuffer.append(ch);//正向旋转graphics.rotate(degree * Math.PI / 180, x, 20);graphics.drawString(ch, x, 20);//反向旋转graphics.rotate(-degree * Math.PI / 180, x, 20);x += 30;}return sBuffer.toString();}public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{doPost(request, response);}
}

注:

在这里,干扰线的颜色和数目都可以自己设定,颜色可以使用随机色,同时显示的每个文字也可以使用随机的颜色,可以增加验证码识别难度,当然在这里我把比较容易混淆的0和O以及I都给去掉了。如果选用经过编码的中文字符的话,也是可以生成中文验证码的

四 login.jsp页面提交表单后,后台的servlet文件HandleLogin.java校验验证码,并进行登录验证

经过上面的三个步骤后,login.jsp应该是可以正确显示验证码了,同时点击验证码图片后会生成一个新的验证码,login.jsp提交表单后HandleLogin.java文件验证验证码时主要是:将输入的验证码中的小写字母转换成大写,再和验证码生成时保存在session中的字符串比较,如果相同,则表示输入正确,同时移除session中设置的值,防止重复提交,爆破密码,HandleLogin.java相关代码如下:

package com.zifangsky.OnlineFriend.servlet.member;import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
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 com.zifangsky.OnlineFriend.model.member.Login;
import com.zifangsky.OnlineFriend.util.DbConn;
import com.zifangsky.OnlineFriend.util.StringUtil;public class HandleLogin extends HttpServlet{private String backNews = "";  //登录状态返回信息public void init(ServletConfig config) throws ServletException{super.init(config);}public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");HttpSession session = request.getSession(true);//获取验证码String validateCode = StringUtil.xssEncode(request.getParameter("validateCode").trim());Object checkcode = session.getAttribute("checkcode");//将输入的验证码中的小写字母转换成大写,再和验证码生成时保存在session中的字符串比较      if(checkcode != null && checkcode.equals(StringUtil.convertToCapitalString(validateCode))){session.removeAttribute("checkcode");continueDoPost(request,response);}else{          response.sendRedirect("login.jsp");return;}}private void continueDoPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{//这里的登录后续操作省略}public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{doPost(request, response);}
}

注1:上面用到的StringUtil是我写的一个字符串相关的方法类,其中用到的方法convertToCapitalString()目的是将一个字符串中的小写字母转换为大写字母,代码如下:

/*** 将一个字符串中的小写字母转换为大写字母* * */public static String convertToCapitalString(String src){char[] array = src.toCharArray();int temp = 0;for (int i = 0; i < array.length; i++){temp = (int) array[i];if (temp <= 122 && temp >= 97){ // array[i]为小写字母array[i] = (char) (temp - 32);}}return String.valueOf(array);}

注2:其中方法xssEncode()是将输入的字符串进行编码,以此避免产生XSS跨站脚本***,用的是commons-lang-2.4.jar里的StringEscapeUtils,代码如下(PS:当然在这里没有什么必要,可以省略):

/*** 字符串XSS过滤,JavaScript过滤,Sql过滤* * @param str 传入的字符串* * @return 转义后的字符串* */public static String xssEncode(String str){String s = StringEscapeUtils.escapeHtml(str);
//      s = StringEscapeUtils.escapeJavaScript(s);
//      s = StringEscapeUtils.escapeSql(s);        return s;   }

转载于:https://blog.51cto.com/983836259/1706029

在JSP中动态生成随机验证码,登录时后台校验验证码,以及如何避免同一个验证码被重复提交爆破密码...相关推荐

  1. Servlet(JSP)中动态生成JPG PNG透明 水印图像

    部分内容摘自互联网,选择精华部分摘入,并加入自己实践内容,记录下,方便后人,方便自己! 1. 生成JPG图片 response.setContentType("image/jpeg" ...

  2. JSP中动态includ与静态includ的区别

    JSP中动态INCLUDE与静态INCLUDE的区别? 动态INCLUDE用jsp:include动作实现 <jsp:include page="included.jsp" ...

  3. jsp中动态include与静态include的区别

    JSP中动态INCLUDE与静态INCLUDE的区别 动态INCLUDE用jsp:include动作实现 <jsp:include page="included.jsp" f ...

  4. word文档中动态生成excel表格(基金公告系列讲解)

    1.本博文仅为了将之前工作中动态生成XBRL文件需求中word文档动态生成excel部分进行了实现(虽然隔着时间比较久),闲暇之余的考虑,应对大批量文件生成时可采用定时任务+多线程技术+redis队列 ...

  5. 生成随机小数的函数python_哪个选项是random库中用于生成随机小数的函数?

    [其它]一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数.试编写代码输出该整数. 要求(1)粘贴代码图片(图片需包括行号),代码不可超过6行(争取4行); (2)粘贴结果图片, ...

  6. android 动态显示表格,在Android Studio中动态生成并显示表格

    我在Android上创建我的第一个应用程序,因此我有低开发android应用程序的经验,而且我也是第一次使用java.在Android Studio中动态生成并显示表格 我想要什么? 我想从Array ...

  7. R语言使用keras包实现卷积自动编码器模型(Convolutional Autoencoder)、加载keras自带的mnist数据集、训练中动态生成每个epoch后模型训练的loss曲线

    R语言使用keras包实现卷积自动编码器模型(Convolutional Autoencoder).加载keras自带的mnist数据集.训练中动态生成每个epoch后模型训练的loss曲线 目录

  8. 使用POI在Excel中动态生成图表工具类(支持柱状、组合、环状图、折线图、等常用图)

    使用POI在Excel中动态生成图表工具类 使用POI在Excel中动态生成图表工具类 由于公司是一个生成报表的机构,之前一直使用pageOffice,但是公司领导就是不买,你说公司那样有钱磨磨唧唧干 ...

  9. js 动态生成html(js根据后台返回数据生成html页面中的table标签)(转义字符)

    js 动态生成html table标签中内容js生成 html代码 js代码 js 动态生成html 触发事件传参字符转义 table标签中内容js生成 html代码 <div><t ...

最新文章

  1. 轻松精通数据库管理之道——运维巡检之四(数据库备份)
  2. logstash使用中遇到的问题
  3. 轻量化CNN网络MobileNet系列详解
  4. 大容量存储方案_基因行业容器存储解决方案
  5. IIS服务在启动默认网站(停止)时显示发生意外错误0x8ffe2740,
  6. 商城文档、商城原型、全局说明、o2o商城、汽车商城、业务逻辑、商城架构图、流程图、版本规划、需求说明、活动、预约、会员、prd、交互说明、页面说明、显示规则、字段说明、操作规则、数据来源、需求规划
  7. Agile Web Application Development with Yii 1.1 and PHP5
  8. 简记mysql在tomcat下和hibernate一起使用,No suitable driver found for的问题
  9. PHP如果某商品下的所有货品库存都为0,则下架该商品
  10. datastore java_Android 使用DataStore存储数据
  11. 小程序云开发(四):云数据库的文件操作之上传头像图片,获取云图片
  12. Python:如何用python编写无限猴子定理
  13. 视频摘要和视频浓缩的区别
  14. 前端MUI+H5+HBuilderX开发APP(IOS,android),后台Springboot,java学习与实践文章,更新中(二)
  15. 使用 PHP 和 MySQL 的安全登录系统
  16. 使用EventLog Analyzer进行日志取证分析
  17. 架构师知识体系(5)--建立自己的知识体系吧
  18. M1 Mac 即将可以玩到更多 Switch 游戏
  19. linux可以识别多少lun,Linux上每个SCSI设备的最大LUN数目是多少(by quqi99)
  20. 摒弃盗版,让我们拥有正版,给你最实用的软件。有效的优化

热门文章

  1. linux下执行mysql的sql文件
  2. java 大小固定_为什么Java堆的最大大小是固定的?
  3. i/o timeout , 希望你不要踩到这个net/http包的坑
  4. 用etcd实现服务注册和发现
  5. 关于Consul的几个问题
  6. 消息中间件Kafka与RabbitMQ谁更胜一筹?
  7. 打造个人专属的微型linux--启动原理篇
  8. 联动下拉框显示省市县
  9. @dynamic 模拟NSManagedObject类的内部实现,AFN的非常规用法
  10. 【平面设计】扁平化设计(Ⅲ)——原则