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的源码浅要剖析Python的内存管理
Apr 16 Python
python中尾递归用法实例详解
Apr 28 Python
Python内置模块hashlib、hmac与uuid用法分析
Feb 12 Python
Python迭代器与生成器用法实例分析
Jul 09 Python
python实现屏保计时器的示例代码
Aug 08 Python
python3 中文乱码与默认编码格式设定方法
Oct 31 Python
配置 Pycharm 默认 Test runner 的图文教程
Nov 30 Python
简单了解python中对象的取反运算符
Jul 01 Python
python openpyxl使用方法详解
Jul 18 Python
使用OpenCV获取图片连通域数量,并用不同颜色标记函
Jun 04 Python
Python脚本破解压缩文件口令实例教程(zipfile)
Jun 14 Python
python 基于DDT实现数据驱动测试
Feb 18 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的安全
2006/10/09 PHP
PHP模块 Memcached功能多于Memcache
2011/06/14 PHP
PHP中的reflection反射机制测试例子
2014/08/05 PHP
PHP中new static()与new self()的区别异同分析
2014/08/22 PHP
php使用CURL模拟GET与POST向微信接口提交及获取数据的方法
2016/09/23 PHP
php封装的表单验证类完整实例
2016/10/19 PHP
php使用curl实现简单模拟提交表单功能
2017/05/15 PHP
js图片自动切换效果处理代码
2013/05/07 Javascript
Jquery的hide及toggle方法让超链接慢慢消失
2013/09/06 Javascript
使用微信小程序开发前端【快速入门】
2016/12/05 Javascript
纯JS实现弹性导航条效果
2017/03/06 Javascript
vue.js实例对象+组件树的详细介绍
2017/10/20 Javascript
swiper移动端轮播插件(触碰图片之后停止轮播)
2017/12/28 Javascript
vue2.0 根据状态值进行样式的改变展示方法
2018/03/13 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
js实现验证码功能
2020/07/24 Javascript
Python中index()和seek()的用法(详解)
2017/04/27 Python
Python简单计算数组元素平均值的方法示例
2017/12/26 Python
python使用TensorFlow进行图像处理的方法
2018/02/28 Python
python版本的仿windows计划任务工具
2018/04/30 Python
Python全排列操作实例分析
2018/07/24 Python
Python3爬虫里关于Splash负载均衡配置详解
2020/07/10 Python
全面解析CSS Media媒体查询使用操作(推荐)
2017/08/15 HTML / CSS
纯CSS实现设置半个字符的样式
2014/07/03 HTML / CSS
CSS3 实现footer 固定在底部(无论页面多高始终在底部)
2019/10/15 HTML / CSS
canvas与html5实现视频截图功能示例
2016/12/15 HTML / CSS
个人找工作的自我评价
2013/10/17 职场文书
《胡杨》教学反思
2014/02/16 职场文书
班级德育工作实施方案
2014/02/21 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
综合素质评价个性发展自我评价
2015/03/06 职场文书
高三英语教学反思
2016/03/03 职场文书
my.ini优化mysql数据库性能的十个参数(推荐)
2021/05/26 MySQL
python plt.plot bar 如何设置绘图尺寸大小
2021/06/01 Python
Docker官方工具docker-registry案例演示
2022/04/13 Servers
MySQL数据库 安全管理
2022/05/06 MySQL