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 相关文章推荐
Django学习笔记之Class-Based-View
Feb 15 Python
Python字符串拼接六种方法介绍
Dec 18 Python
Python实现求数列和的方法示例
Jan 12 Python
Python操作MySQL数据库的方法
Jun 20 Python
解决python通过cx_Oracle模块连接Oracle乱码的问题
Oct 18 Python
python项目对接钉钉SDK的实现
Jul 15 Python
Python3 mmap内存映射文件示例解析
Mar 23 Python
实现ECharts双Y轴左右刻度线一致的例子
May 16 Python
在终端启动Python时报错的解决方案
Nov 20 Python
python 实现Requests发送带cookies的请求
Feb 08 Python
教你使用Python pypinyin库实现汉字转拼音
May 27 Python
Python实现查询剪贴板自动匹配信息的思路详解
Jul 09 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
PHP4实际应用经验篇(9)
2006/10/09 PHP
php中计算未知长度的字符串哪个字符出现的次数最多的代码
2012/08/14 PHP
php中unserialize返回false的解决方法
2014/09/22 PHP
ThinkPHP打水印及设置水印位置的方法
2016/10/14 PHP
PHP实现用户登录的案例代码
2018/05/10 PHP
ThinkPHP5.0多个文件上传后找不到临时文件的修改方法
2018/07/30 PHP
php精度计算的问题解析
2019/06/21 PHP
javascript编程起步(第二课)
2007/01/10 Javascript
javascript prototype 原型链
2009/03/12 Javascript
基于jquery实现拆分姓名的方法(纯JS版)
2013/05/08 Javascript
JS图片自动轮换效果实现思路附截图
2014/04/30 Javascript
浅析javascript中function 的 length 属性
2014/05/27 Javascript
js获取元素相对窗口位置的实现代码
2014/09/28 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
2015/03/25 Javascript
详解JavaScript编程中的数组结构
2015/10/24 Javascript
nodejs socket实现的服务端和客户端功能示例
2017/06/02 NodeJs
mongoose更新对象的两种方法示例比较
2017/12/19 Javascript
layui固定下拉框的显示条数(有滚动条)的方法
2019/09/10 Javascript
vue学习笔记之给组件绑定原生事件操作示例
2020/02/27 Javascript
使用Python脚本和ADB命令实现卸载App
2017/02/10 Python
Python 中pandas.read_excel详细介绍
2017/06/23 Python
python爬虫获取淘宝天猫商品详细参数
2020/06/23 Python
python 找出list中最大或者最小几个数的索引方法
2018/10/30 Python
详解python中的index函数用法
2019/08/06 Python
pytorch 共享参数的示例
2019/08/17 Python
详解pandas.DataFrame.plot() 画图函数
2020/06/14 Python
Pycharm2020.1安装无法启动问题即设置中文插件的方法
2020/08/07 Python
HTML+CSS3模拟心的跳动实例代码
2017/09/05 HTML / CSS
丝芙兰波兰:Sephora.pl
2018/03/25 全球购物
西班牙在线药店:DosFarma
2020/03/28 全球购物
英语专业学生个人求职信范文
2014/01/06 职场文书
医院学雷锋活动策划方案
2014/02/15 职场文书
小学庆六一活动方案
2014/02/28 职场文书
党员考试作弊检讨书1000字
2015/02/16 职场文书
关于元旦的广播稿2016
2015/12/17 职场文书
MySQL系列之十四 MySQL的高可用实现
2021/07/02 MySQL