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();
    }
  }
}

(0)

相关推荐

  • java模拟cookie登陆操作

    在使用java访问URL时,如果该URL需要身份验证,那么就不能够直接访问,因为没有登陆.那么,如何解决这个问题呢? 方法是使用java模拟登陆,登陆后记录下cookie信息,在下次发起请求时时将cookie发送过去用以表明身份,这样就能够访问带有权限的URL了. 下面首先介绍使用java模拟登陆. // 连接地址(通过阅读html源代码获得,即为登陆表单提交的URL) String surl = "http://login.goodjobs.cn/index.php/action/UserLo

  • JavaWeb登陆功能实现代码

    本文实例为大家分享了JavaWeb登陆功能的方法,供大家参考,具体内容如下 首先我们要JavaWeb登陆的基本流程:JSP页面发送请求-->Servlet-->Servlet通过调用方法从数据库中得到数据并将结果返回页面. 我们先建立三个jsp页面,包括login.jsp(登陆页面).index.jsp(显示登陆成功后的信息).error.jsp(登录失败的页面),其中后两个页面的内容可以随意写,而login.jsp页面的主要内容如下: <form action="LoginS

  • Java使用新浪微博API通过账号密码方式登陆微博的实例

    今天下了个新浪微博的API研究研究,目前实现了发布微博功能,包括带图片的微博.为了安全,新浪微博的API中并没有提供用微博帐号密码登录的功能,而是采用OAuth授权,用户通过浏览器访问新浪网站登录,登录成功后,浏览器再返回key和secret给程序. main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.an

  • App登陆java后台处理和用户权限验证

    最近做一个app项目,后台我独自一人开发,开发任务顺序安排上没有把登陆,注册和权限验证这些基本功能放在第一阶段开发,现在是部分业务相关功能已经完成,但是用户入口竟然还没有,只能说明当初需求分析的时候还是太过于着急了,把最基本的用户入口给放到后面了. 现在就需要在现有代码的基础上添加用户登录和权限验证功能. 关于登录和权限验证方面,参照以前做iOS的开发经验,App端提供用户名和密码换取token,每次通过换取的token请求需要登陆权限的操作. 现在反过来,我就需要考虑下面几个问题: 1.在现有

  • JAVA实现简单系统登陆注册模块

    前期准备 首先要先明确有个大体的思路,要实现什么样的功能,了解完成整个模块要运用到哪些方面的知识,以及从做的过程中去发现自己的不足.技术方面的进步大都都需要从实践中出来的. 功能:用户注册功能+系统登录功能+生成验证码 知识:窗体设计.数据库设计.JavaBean封装属性.JDBC实现对数据库的连接.验证码(包括彩色验证码)生成技术,还有就些比如像使用正则表达式校验用户注册信息.随机获得字符串.对文本可用字符数的控制等 设计的模块预览图: 彩色验证码预览图: 所用数据库:MySQL 数据库设计

  • cookie、session和java过滤器结合实现登陆程序

    cookie.session和过滤器通常都是用在web应用中,cookie和session用来保存一定的数据,过滤器Filter则是在浏览器发出请求之后,而后台执行特定的请求之前发生一定的作用.之所以把这三个放一起,是因为有很多时候都会是把他们结合在一起使用,例如有些登陆程序. cookie是浏览器的机制,session是服务器的机制,但是实际上cookie也是由服务器生成的,之后返回给浏览器的,并不是浏览器本身生成.当浏览器发送某个请求时,如果拥有有效的cookie则会把这个cookie带在一

  • java客户端登陆服务器用户名验证

    本文实例为大家分享了java客户端登陆服务器用户名验证的具体实现代码,供大家参考,具体内容如下 客户端通过键盘录入用户名,服务端对用户名进行验证.  如果用户名存在,服务端显示xxx已登录,客户端显示xxx,欢迎登陆. 如果用户名不存在,服务端显示xxx尝试登陆,客户端显示xxx,用户名不存在.  最多登陆三次,防止暴力登陆. import java.io.*; import java.net.*; /* *客户端 */ class client { public static void mai

  • java实现京东登陆示例分享

    复制代码 代码如下: package com.lkb.test; import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map; import org.apache.http.HttpResponse;import org.apache.http.client.ResponseHandler;import org.ap

  • Java的Struts框架中登陆功能的实现和表单处理器的使用

    实现Struts登录 1.jar包拷贝 首先是建立java web项目,之后打开我们我们下载好strtus框架,Struts-1.2.9-bin文件夹和struts-1.2.9.src源文件文件夹.在bin文件夹中的lib文件中拷贝struts的jar包,拷贝到我们自己项目struts_login –>lib文件夹下. 2.web.xml文件配置 找到Struts-1.2.9-bin中Struts-1.2.9-bin-->webapps下的struts实例struts-blank中的strut

  • JAVA简单链接Oracle数据库 注册和登陆功能的实现代码

    复制代码 代码如下: //User 用户的基本信息,也是USERINFO表中的3个列package 登陆判断; public class User { private String name;  private String loginname;  private String loginpsw;  public String getName() {   return name;  }  public void setName(String name) {   this.name = name;

随机推荐