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

 更新时间:2016年05月25日 15:35:54   作者:死神的丧钟  
Java的SSH三大Web开发框架中,对于验证码这一基本功能的处理都比较得心应手,接下来我们就来看看整理出的Java Web开发过程中登陆模块的验证码的实现方式总结:

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

图文验证码的原理
在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(); 
    } 
  } 
} 

2016525153112542.png (514×123)

相关文章

  • Django基础知识 URL路由系统详解

    Django基础知识 URL路由系统详解

    这篇文章主要介绍了Django基础知识 URL路由系统详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python读取txt数据的操作步骤

    python读取txt数据的操作步骤

    这篇文章主要介绍了python读取txt数据的操作步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • 解决Python复杂zip文件的解压问题

    解决Python复杂zip文件的解压问题

    这篇文章主要介绍了Python复杂zip文件的解压,通过配合 shutil 与 os 标准库中的相关功能,实现将指定任意 zip 压缩包,完好地解压到指定的目录中,需要的朋友可以参考下
    2021-12-12
  • python中注释用法简单示例

    python中注释用法简单示例

    注释即对程序代码的解释,在写程序时需适当使用注释,以方便自己和他人理解程序各部分的作用,下面这篇文章主要给大家介绍了关于python中注释用法的相关资料,需要的朋友可以参考下
    2023-02-02
  • Python分析学校四六级过关情况

    Python分析学校四六级过关情况

    这篇文章主要为大家详细介绍了利用Python分析学校四六级过关情况,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • python NetworkX库生成并绘制带权无向图

    python NetworkX库生成并绘制带权无向图

    这篇文章主要为大家介绍了python NetworkX库生成并绘制带权无向图的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python实现1-9数组形成的结果为100的所有运算式的示例

    Python实现1-9数组形成的结果为100的所有运算式的示例

    下面小编就为大家带来一篇Python实现1-9数组形成的结果为100的所有运算式的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Mac下PyCharm快捷键分享

    Mac下PyCharm快捷键分享

    这篇文章主要介绍了Mac下PyCharm快捷键,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • python线程join方法原理解析

    python线程join方法原理解析

    这篇文章主要介绍了python线程join方法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 在django模板中实现超链接配置

    在django模板中实现超链接配置

    今天小编就为大家分享一篇在django模板中实现超链接配置,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08

最新评论