Java Web开发过程中登陆模块的验证码的实现方式总结


Posted in Python onMay 25, 2016

验证码及它的作用
验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。

图文验证码的原理
在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。

实现方式总结
1 验证码生成类RandomCode
RandomCode是一个生成验证码的工具类,支持英文和数字验证码,验证码包括英文大小写和数组,其中英文i、o和数字0、1因为容易产生混淆,不包括在生成验证码中。RandomCode支持输出jpg/bmp/png/gif图片格式的验证码。

/** 
 * RandomCode验证码可以通过静态方法和实例方法生成。 
 * 
 * 静态方法: 
 * 
 * //生成长度为4的随机验证码 
 * String code = RandomCode.randomString(4); 
 * 
 * //把验证码图片输入到response输出流中 
 * //图片格式jpg 
 * OutputStream os = response.getOutputStream(); 
 * RandomCode.write(code, 120, 30, os, "jpg"); 
 * 
 * 实例方法: 
 * 
 * //实例化验证码类 
 * RandomCode rc = new RandomCode(4); 
 * 
 * //把验证码图片输入到response输出流中 
 * //图片格式jpg 
 * OutputStream os = response.getOutputStream(); 
 * rc.write(120, 30, os, "jpg"); 
 * 
 * //获取验证码字符串 
 * String code = rc.getCode(); 
 * 
 */ 
public class RandomCode { 
  /** 
   * 随机验证码字符 
   */ 
  private static String base = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"; 
   
  /** 
   * 随机验证码长度 
   */ 
  private int length = 4; 
   
  /** 
   * 验证码字符串 
   */ 
  private String code; 
 
  /** 
   * 4位随机验证码 
   */ 
  public RandomCode(){ 
    this.code = RandomCode.randomString(this.length); 
  } 
   
  public RandomCode(int length){ 
    if(length > 0){ 
      this.length = length; 
    } 
     
    this.code = RandomCode.randomString(this.length); 
  } 
   
  /** 
   * 生成验证码图片 
   * @param width 图片宽度 
   * @param height 图片高度 
   * @return 
   */ 
  public BufferedImage toImage(int width, int height){ 
    return RandomCode.toImage(this.code, width, height); 
  } 
   
  /** 
   * 输出验证码图片,默认图片格式jpeg 
   * @param width 
   * @param height 
   * @param os 
   * @throws IOException 
   */ 
  public void write(int width, int height, OutputStream os) throws IOException{ 
    RandomCode.write(code, width, height, os, "jpeg"); 
  } 
   
  /** 
   * 输出验证码图片 
   * @param width 
   * @param height 
   * @param os 
   * @param format 图片格式,支持jpg/jpeg/bmp/gif/png 
   * @throws IOException 
   */ 
  public void write(int width, int height, OutputStream os, String format) throws IOException{ 
    RandomCode.write(code, width, height, os, format); 
  } 
 
  public int getLength() { 
    return length; 
  } 
   
  public String getCode() { 
    return code; 
  } 
   
  /** 
   * 静态方法 
   * 生成随机字符串 
   * @param length 字符串长度 
   * @return 随机字符串 
   */ 
  public static String randomString(int length){ 
    Random random = new Random(); 
    StringBuffer sb = new StringBuffer(); 
    for(int i = 0; i < length; i++){ 
      sb.append(base.charAt(random.nextInt(base.length()))); 
    } 
    return sb.toString(); 
  } 
   
  /** 
   * 静态方法 
   * 输出验证码图片 
   * @param code 验证码字符串 
   * @param width 图片宽度 
   * @param height 图片高度 
   * @param os 图片输出流 
   * @param format 图片格式,支持jpg/jpeg/bmp/gif/png 
   * @throws IOException 
   */ 
  public static void write(String code, int width, int height, OutputStream os, String format) throws IOException{ 
    BufferedImage image = toImage(code, width, height); 
    ImageIO.write(image, format, os); 
  } 
   
  /** 
   * 静态方法 
   * 输出验证码图片,默认图片格式jpeg 
   * @param code 验证码字符串 
   * @param width 图片宽度 
   * @param height 图片高度 
   * @param os 图片输出流 
   * @throws IOException 
   */ 
  public static void write(String code, int width, int height, OutputStream os) throws IOException{ 
    write(code, width, height, os, "jpeg"); 
  } 
   
  /** 
   * 静态方法 
   * 字符串转成验证码图片 
   * @param code 验证码字符串 
   * @param width 验证码图片宽度,单位像素 
   * @param height 验证码图片高度,单位像素 
   * @return 
   */ 
  public static BufferedImage toImage(String code, int width, int height){ 
    //字体大小 
    int fontSize = (int)Math.ceil(height * 0.9); 
    if(fontSize < 20){ 
      fontSize = 20; 
    } 
     
    //字体在Y坐标上的位置 
    int positionY = (int)Math.ceil(height * 0.8); 
     
    int lenCode = code.length(); 
     
    //计算字体宽度 
    int fontWidth = width / (lenCode + 2); 
     
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); 
    Graphics g = image.getGraphics(); 
     
    //图片背景随机颜色 
    g.setColor(randomColor(new Random(), 200, 250)); 
    g.fillRect(0, 0, width, height); 
     
    //设置字体 
    g.setFont(new Font("Times New Roman", Font.BOLD, fontSize)); 
     
    //在图片上画纵横交错的线,达到混淆效果 
    drawLines(g, width, height); 
     
    //在图片上画验证码 
    drawString(g, code, fontWidth, positionY); 
     
    g.dispose(); 
     
    return image; 
  } 
   
  /** 
   * 静态方法 
   * 在图片上话位子 
   * @param g 
   * @param code 验证码字符串 
   * @param fontWidth 字体宽度 
   * @param positionY 字体Y坐标 
   */ 
  private static void drawString(Graphics g, String code, int fontWidth, int positionY){ 
    int len = code.length(); 
    Random random = new Random(); 
    for(int i = 0; i < len; i++){ 
      g.setColor(randomColor(random)); 
      g.drawString(String.valueOf(code.charAt(i)), (i + 1) * fontWidth, positionY); 
    } 
  } 
   
  private static Color randomColor(Random random){ 
    int r = random.nextInt(255); 
    int g = random.nextInt(255); 
    int b = random.nextInt(255); 
    return new Color(r, g, b); 
  } 
   
  private static Color randomColor(Random random, int fc, int bc){ 
    if(fc > 255){ 
      fc = 255; 
    } 
       
    if(bc > 255){ 
      bc = 255; 
    }   
     
    int diff = bc-fc; 
    int r = fc + random.nextInt(diff); 
    int g = fc + random.nextInt(diff); 
    int b = fc + random.nextInt(diff); 
    return new Color(r,g,b); 
  } 
   
  /** 
   * 静态方法 
   * 画纵横交错的线 
   * @param g 
   * @param width 验证码图片宽度 
   * @param height 验证码图片高度 
   */ 
  private static void drawLines(Graphics g, int width, int height){ 
    Random random = new Random(); 
     
    //线的数量 
    int count = ((int)(Math.ceil(random.nextDouble() * 100))) + 100;     
     
    for(int i = 0; i < count; i++){ 
      int fc = 160 + (int)Math.ceil(random.nextDouble() * 40); 
      int bc = 200 + (int)Math.ceil(random.nextDouble() * 55); 
      g.setColor(randomColor(random, fc, bc)); 
       
      int x = random.nextInt(width); 
      int y = random.nextInt(height); 
      int xl = random.nextInt(width / 5); 
      int yl = random.nextInt(height / 5);       
      g.drawLine(x, y, x + xl, y + yl); 
    } 
  }   
}

2 Servlet返回验证码
请求路径http://<网站路径>/random/code/servlet

@WebServlet("/random/code/servlet") 
public class RandomCodeServlet extends HttpServlet { 
  private static final long serialVersionUID = 1L; 
 
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    // 验证码图片宽度,单位像素 
    int width = 120; 
    // 验证码图片高度,单位像素 
    int height = 30; 
    // 验证码图片格式 
    String format = "png"; 
    // 验证码字符长度 
    int len = 4; 
 
    // 设置图片格式 
    response.setContentType("image/" + format); 
 
    // 禁止浏览器缓存图片 
    response.setHeader("Pragma", "no-cache"); 
    response.setHeader("Cache-Control", "no-cache"); 
    response.setDateHeader("Expires", 0); 
 
    String code = RandomCode.randomString(len); 
 
    // 把图片输出到response输出流 
    RandomCode.write(code, width, height, response.getOutputStream(), format); 
  } 
}

3 Strust2返回验证码

public class RandomCodeAction extends ActionSupport { 
  private static final long serialVersionUID = -7515645222798283236L; 
 
  /** 
   * 获取验证码 
   */ 
  public void generateCode() { 
    HttpServletResponse response = ServletActionContext.getResponse(); 
 
    // 验证码图片宽度,单位像素 
    int width = 120; 
    // 验证码图片高度,单位像素 
    int height = 30; 
    // 验证码图片格式 
    String format = "png"; 
    // 验证码字符长度 
    int len = 4; 
 
    // 设置图片格式 
    response.setContentType("image/" + format); 
 
    // 禁止浏览器缓存图片 
    response.setHeader("Pragma", "no-cache"); 
    response.setHeader("Cache-Control", "no-cache"); 
    response.setDateHeader("Expires", 0); 
 
    String code = RandomCode.randomString(len); 
 
    // 把图片输出到response输出流 
    try { 
      RandomCode.write(code, width, height, response.getOutputStream(), format); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
  } 
}

Struts2的验证码配置

<package name="pkg-random-code" namespace="/" extends="struts-default"> 
  <action name="randomCode_*" method="{1}" class="com.rhui.web.action.RandomCodeAction"></action> 
</package>

请求路径http://<网站路径>/randomCode_generateCode.do

4 SpringMVC返回验证码
请求路径http://<网站路径>/random/code/generate.do

package com.rhui.web.controller; 
 
import java.io.IOException; 
 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
 
import com.rhui.util.RandomCode; 
 
@Controller 
@RequestMapping("/random/code") 
public class RandomCodeController { 
  @RequestMapping("/generate.do") 
  public void generateCode(HttpServletResponse response) { 
    // 验证码图片宽度,单位像素 
    int width = 120; 
    // 验证码图片高度,单位像素 
    int height = 30; 
    // 验证码图片格式 
    String format = "png"; 
    // 验证码字符长度 
    int len = 4; 
 
    // 设置图片格式 
    response.setContentType("image/" + format); 
 
    // 禁止浏览器缓存图片 
    response.setHeader("Pragma", "no-cache"); 
    response.setHeader("Cache-Control", "no-cache"); 
    response.setDateHeader("Expires", 0); 
 
    String code = RandomCode.randomString(len); 
 
    // 把图片输出到response输出流 
    try { 
      RandomCode.write(code, width, height, response.getOutputStream(), format); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
  } 
}

Java Web开发过程中登陆模块的验证码的实现方式总结

Python 相关文章推荐
列举Python中吸引人的一些特性
Apr 09 Python
pandas对指定列进行填充的方法
Apr 11 Python
python下解压缩zip文件并删除文件的实例
Apr 24 Python
Python 使用 attrs 和 cattrs 实现面向对象编程的实践
Jun 12 Python
python几种常用功能实现代码实例
Dec 25 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
Python实现Keras搭建神经网络训练分类模型教程
Jun 12 Python
Python变量格式化输出实现原理解析
Aug 06 Python
PyCharm设置注释字体颜色以及是否倾斜的操作
Sep 16 Python
python用Configobj模块读取配置文件
Sep 26 Python
python 生成器需注意的小问题
Sep 29 Python
Python爬虫基础之简单说一下scrapy的框架结构
Jun 26 Python
剖析Python的Twisted框架的核心特性
May 25 #Python
实例解析Python的Twisted框架中Deferred对象的用法
May 25 #Python
详解Python的Twisted框架中reactor事件管理器的用法
May 25 #Python
使用Python的Twisted框架编写非阻塞程序的代码示例
May 25 #Python
Python的Twisted框架中使用Deferred对象来管理回调函数
May 25 #Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
May 25 #Python
Python的Twisted框架上手前所必须了解的异步编程思想
May 25 #Python
You might like
PHP 时间转换Unix时间戳代码
2010/01/22 PHP
php数组函数序列之array_push() 数组尾部添加一个或多个元素(入栈),返回新长度。
2011/11/07 PHP
PHP取整函数:ceil,floor,round,intval的区别详细解析
2013/08/31 PHP
phpStudy vscode 搭建debug调试的教程详解
2020/07/28 PHP
学习YUI.Ext第七日-View&amp;JSONView Part Two-一个画室网站的案例
2007/03/10 Javascript
jquery插件 cluetip 关键词注释
2010/01/12 Javascript
被jQuery折腾得半死,揭秘为何jQuery为何在IE/Firefox下均无法使用
2010/01/22 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
document.getElementBy(&quot;id&quot;)与$(&quot;#id&quot;)有什么区别
2013/09/22 Javascript
Nodejs学习笔记之测试驱动
2015/04/16 NodeJs
js获取本机操作系统类型的两种方法
2015/12/19 Javascript
基于jQuery实现Ajax验证用户名是否存在实例
2016/03/30 Javascript
基于JQuery实现的跑马灯效果(文字无缝向上翻动)
2016/12/02 Javascript
Vue.js仿Metronic高级表格(一)静态设计
2017/04/17 Javascript
JS实现json的序列化和反序列化功能示例
2017/06/13 Javascript
angular实现spa单页面应用实例
2017/07/10 Javascript
jQuery替换节点元素的操作方法
2018/03/18 jQuery
vue自定v-model实现表单数据双向绑定问题
2018/09/03 Javascript
微信小程序自定义组件components(代码详解)
2019/10/21 Javascript
JavaScript数值类型知识汇总
2019/11/17 Javascript
vue实现购物车结算功能
2020/06/18 Javascript
javascript递归函数定义和用法示例分析
2020/07/22 Javascript
在vue中动态修改css其中一个属性值操作
2020/12/07 Vue.js
Python定时执行之Timer用法示例
2015/05/27 Python
Zookeeper接口kazoo实例解析
2018/01/22 Python
python3连接MySQL数据库实例详解
2018/05/24 Python
python滑块验证码的破解实现
2019/11/10 Python
python编写微信公众号首图思路详解
2019/12/13 Python
Python第三方库安装缓慢的解决方法
2021/02/06 Python
基层工作经验证明样本
2014/11/16 职场文书
个人工作保证书
2015/02/28 职场文书
上班旷工检讨书
2015/08/15 职场文书
2016参观监狱警示教育活动心得体会
2016/01/15 职场文书
python 实现mysql自动增删分区的方法
2021/04/01 Python
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis
MySQL8.0的WITH查询详情
2021/08/30 MySQL