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连接池实现示例程序
Nov 26 Python
Python中给List添加元素的4种方法分享
Nov 28 Python
Python简单格式化时间的方法【strftime函数】
Sep 18 Python
Windows系统下多版本pip的共存问题详解
Oct 10 Python
python如何在列表、字典中筛选数据
Mar 19 Python
分分钟入门python语言
Mar 20 Python
Python多进程原理与用法分析
Aug 21 Python
python读写csv文件方法详细总结
Jul 05 Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
Dec 05 Python
使用keras实现Precise, Recall, F1-socre方式
Jun 15 Python
OpenCV利用python来实现图像的直方图均衡化
Oct 21 Python
Elasticsearch 数据类型及管理
Apr 19 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中filter函数校验数据的方法详解
2015/07/31 PHP
关于PHP中字符串与多进制转换函数的实例代码
2016/11/03 PHP
PHP编程 SSO详细介绍及简单实例
2017/01/13 PHP
提高 DHTML 页面性能
2006/12/25 Javascript
JavaScript与Div对层定位和移动获得坐标的实现代码
2010/09/08 Javascript
为jQuery增加join方法的实现代码
2010/11/28 Javascript
JavaScript对象学习经验整理
2013/10/12 Javascript
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
javaScript使用EL表达式的几种方式
2014/05/27 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
学习javascript面向对象 掌握创建对象的9种方式
2016/01/04 Javascript
javascript执行环境及作用域详解
2016/05/05 Javascript
jQuery链式调用与show知识浅析
2016/05/11 Javascript
JavaScript实现复制文章自动添加版权
2016/08/02 Javascript
js导出excel文件的简洁方法(推荐)
2016/11/02 Javascript
angularjs点击图片放大实现上传图片预览
2017/02/24 Javascript
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
二维码图片生成器QRCode.js简单介绍
2017/08/18 Javascript
JS简单实现父子窗口传值功能示例【未使用iframe框架】
2017/09/20 Javascript
React-intl 实现多语言的示例代码
2017/11/03 Javascript
js中split()方法得到的数组长度问题
2018/07/19 Javascript
nodejs中实现修改用户路由功能
2019/05/24 NodeJs
javascript实现智能手环时间显示
2020/09/18 Javascript
vue3+typeScript穿梭框的实现示例
2020/12/29 Vue.js
[53:15]Newbee vs Pain 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python给图像添加噪声具体操作
2019/03/03 Python
Python3批量移动指定文件到指定文件夹方法示例
2019/09/02 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
英国助听器购物网站:Hearing Direct
2018/08/21 全球购物
Tessabit日本:集世界奢侈品和设计师品牌的意大利精品买手店
2020/01/07 全球购物
付款委托书范本
2014/04/04 职场文书
婚假请假条格式及范文
2014/04/10 职场文书
初中生操行评语大全
2014/04/24 职场文书
求职教师自荐书
2014/06/19 职场文书
2015年信访维稳工作总结
2015/04/07 职场文书
话题作文之呼唤
2019/12/18 职场文书