JAVAWEB项目如何实现验证码

1.图文验证码的原理

      在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。

 

2.验证码所需的技术

         i.因为验证码中的文字,数字,应为都是可变的,故要用到随机生成数技术。

       ii.如果验证码中包含汉字,则要用到汉字生成技术.

       iii.可以使用Ajax技术实现局部刷新

       iv.可以使用图片的缩放和旋转技术,

       vi.随机绘制干扰线(可以是折现,直线等)

       vii.如果考虑到验证码的安全性,可以使用MD5加密.


验证码模块实例

1.编写生成英文,数字,汉字随机生成的Servlet类.源代码如下:


package com.servlet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 随机生成英文,数字,汉字验证码
 * 
 *
 */
public class PictureCheckCode extends HttpServlet{

  	//定义变量
	//序列化      Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。
 	private static final long serialVersionUID = 1L;

 	//构造方法
	 public PictureCheckCode() {
		 super();
  	}

  	//重写destory方法(服务结束时,调用destory()方法,在init()方法中创建的任何资源都应该被清除和释放)
 	public void destroy() {
  		super.destroy();
 	}
	
 	//重写init方法(在init()方法中,servlet创建和初始化它在处理请求时需要用到的资源)
  	public void init() throws ServletException {
 		super.init();
  	}  
	
	//获得随机生成的颜色  
        public Color getRandColor(int s, int e){ 
    	
               Random random = new Random();  
               if(s > 255) s = 255;  
               if(e > 255) e = 255;  
               int r, g, b;  
               r = s + random.nextInt(e - s);    //随机生成RGB颜色中的r值  
               g = s + random.nextInt(e - s);    //随机生成RGB颜色中的g值  
               b = s + random.nextInt(e - s);    //随机生成RGB颜色中的b值  
               return new Color(r, g, b);  
        }     
    
	//重写service方法
 	protected void service(HttpServletRequest request, HttpServletResponse response)
 			 throws ServletException, IOException {
		
  		//设置不缓存  
                response.setHeader("Pragma", "No-cache");  
                response.setHeader("Cache-Control", "No-cache"); 
                //设置过期的时间期限
                response.setDateHeader("Expires", 0);
                //指定生成的响应图片,一定不能缺少这句话,否则错误.  
                response.setContentType("image/jpeg");  
        
                //指定生成验证码的宽度和高度
               int width = 86;
               int height = 22;
               //创建BufferedImage对象,其作用相当于一图片  
               BufferedImage image  =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
        
               //创建Graphics对象,其作用相当于画笔 
               Graphics g = image.getGraphics(); 
               //创建Grapchics2D对象(绘制2D图形) 
               Graphics2D g2d = (Graphics2D)g; //把Graphics类的对象g,强制转换成Graphics2D类的对象g2d 
        
               Random random = new Random();  
               //定义字体样式(bold 粗体)
               Font mfont = new Font("楷体", Font.BOLD, 16);   
               g.setColor(getRandColor(200, 250)); 
               //绘制背景 
               g.fillRect(0, 0, width, height);
               //设置字体 
               g.setFont(mfont);
               g.setColor(getRandColor(180, 200));
        
               //绘制100条颜色和位置全部为随机产生的线条,该线条为2f  
               for(int i = 0; i < 100; i++){  
                  int x = random.nextInt(width - 1);  
                  int y = random.nextInt(height - 1);  
                  int x1 = random.nextInt(6) + 1;  
                  int y1 = random.nextInt(12) + 1;  
                  //定制线条样式(CAP_BUTT为一种线端       JOIN_BEVEL两条线连接时,连接处的形状) 
                  BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);  
                  //Line2D。Double 根据指定坐标(x + x1, y + y1) (x, y)构造一条线
                  Line2D line = new Line2D.Double(x, y, x + x1, y + y1);  
                  g2d.setStroke(bs);
                  //绘制直线
                  g2d.draw(line);
               }
            
               //输出由英文,数字,和中文随机组成的验证文字,具体的组合方式根据生成随机数确定。  
               String sRand = "";  
               String ctmp = "";  
               int itmp = 0;  
               //制定输出的验证码为四位  
               for(int i = 0; i < 4; i++){  
                  switch(random.nextInt(3)){  
                    case 1:
                            itmp = random.nextInt(26) + 65;      //生成A-Z的字母 
                            ctmp = String.valueOf((char)itmp);  
                            break;  
                    case 2:                   //生成汉字  
                            String[] rBase= {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};   
                            //生成第一位区码  
                            int r1 = random.nextInt(3) + 11;    //生成11到14之间的随机数
                            String str_r1 = rBase[r1];  
                            //生成第二位区码  
                            int r2;  
                            if(r1 == 13){  
                                r2 = random.nextInt(7);         //生成0到7之间的随机数  
                            }else{  
                                r2 = random.nextInt(16);        //生成0到16之间的随机数
                            }  
                            String str_r2 = rBase[r2];  
                            //生成第一位位码  
                            int r3 = random.nextInt(6) + 10;    //生成10到16之间的随机数
                            String str_r3 = rBase[r3];  
                            //生成第二位位码  
                            int r4;  
                            if(r3 == 10){  
                                r4 = random.nextInt(15) + 1;    //生成1到16之间的随机数 
                            }else if(r3 == 15){  
                                r4 = random.nextInt(15);        //生成0到15之间的随机数
                            }else{  
                                r4 = random.nextInt(16);        //生成0到16之间的随机数
                            }  
                            String str_r4 = rBase[r4];  
                            //将生成的机内码转换为汉字  
                            byte[] bytes = new byte[2];  
                            //将生成的区码保存到字节数组的第一个元素中  
                            String str_12 = str_r1 + str_r2;  
                            int tempLow = Integer.parseInt(str_12, 16);  
                            bytes[0] = (byte) tempLow;  
                            //将生成的位码保存到字节数组的第二个元素中  
                            String str_34 = str_r3 + str_r4;  
                            int tempHigh = Integer.parseInt(str_34, 16);  
                            bytes[1] = (byte)tempHigh; 
                     
                            ctmp = new String(bytes);           //根据字节数组生成汉字
                            //测试参数
//                          System.out.println("生成汉字:" + ctmp);  
                            break;  
                     default:  
                            itmp = random.nextInt(10) + 48;     //生成0~9的数字
                            ctmp = String.valueOf((char)itmp);  
                            break;  
                  }
                  sRand += ctmp;  
                  Color color = new Color(20 + random.nextInt(110), 20 + random.nextInt(110), random.nextInt(110));  
                  g.setColor(color);  
            
                  //将生成的随机数进行随机缩放并旋转制定角度                        PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示  
                  //将文字旋转制定角度  
                  Graphics2D g2d_word = (Graphics2D)g;  
                  AffineTransform trans = new AffineTransform();
                  //初始化 RotateTransform 类的一个新实例,该实例具有指定的角度和中心点
                  trans.rotate((45) * 3.14 / 180, 15 * i + 8, 7);  
                  //缩放文字  
                  float scaleSize = random.nextFloat() + 0.8f;  
                  if(scaleSize > 1f) scaleSize = 1f;  
                  trans.scale(scaleSize, scaleSize);  
                  g2d_word.setTransform(trans);  
                  g.drawString(ctmp, 15 * i + 18, 14);  
               }  
               //将生成的验证码保存到Session中  
               HttpSession session = request.getSession(true);  
               session.setAttribute("randCheckCode", sRand);  
               //释放g所占用的系统资源
               g.dispose();   
               //输出图片
               ImageIO.write(image, "JPEG", response.getOutputStream());  
        }  
}

 

 2.配置Servlet

 在web.xml中的配置如下:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>
  <servlet>
    <description>输出验证码</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>PictureCheckCode</servlet-name>
    <servlet-class>com.servlet.PictureCheckCode</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>PictureCheckCode</servlet-name>
    <url-pattern>/picturecheckcode</url-pattern>
  </servlet-mapping>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


3.测试验证码

      可以编写JSP页面来验证是否可以输出验证码图片,JSP代码如下:

    1.index.jsp:显示界面

  1. <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>  
  2.   
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  4. <html>  
  5.     <head>  
  6.         <title>验证码</title>  
  7.         <script language="javascript">  
  8. function myReload() {  
  9.     document.getElementById("CreateCheckCode").src = document  
  10.             .getElementById("CreateCheckCode").src  
  11.             + "?nocache=" + new Date().getTime();  
  12. }  
  13. </script>  
  14.     </head>  
  15.   
  16.     <body>  
  17.         <form action="Check.jsp" method="post">  
  18.             <input name="checkCode" type="text" id="checkCode" title="验证码区分大小写"  
  19.                 size="8" ,maxlength="4" />  
  20.             <img src="PictureCheckCode" id="CreateCheckCode" align="middle">  
  21.             <a href="" οnclick="myReload()"> 看不清,换一个</a>  
  22.             <input type="submit" value="提交" />  
  23.         </form>  
  24.     </body>  
  25. </html>  


 

2.Check.jsp :主要验证提交的数据是否和Session中保存的验证码是否相同

  1. <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>  
  2. <html>  
  3.   <head>  
  4.     <title>验证码校验</title>  
  5.   </head>  
  6.     
  7.   <body>  
  8.     <%  
  9.         String checkcode=request.getParameter("checkCode");  
  10.         if(checkcode.equals("")||checkcode==null){  
  11.             out.print("<script>alert('请输入验证码');window.location.href('index.jsp')</script>");  
  12.         }else{  
  13.             if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){  
  14.                 out.print("<script>alert('验证码不正确,请重新输入');history.back(-1);</script>");  
  15.             }else{  
  16.                 out.print("登录成功");  
  17.             }  
  18.         }  
  19.      %>  
  20.   </body>  
  21. </html>  


 

3.工程项目结构,及运行截图 


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现图片验证码主要需要以下几个步骤: 1. 生成随机字符串:使用 Java 的随机数生成器生成指定长度的随机字符串,可以使用 UUID、SecureRandom等类实现。 2. 将随机字符串绘制到图片上:使用 Java 的 Graphics2D 类将随机字符串绘制到一个 BufferedImage 对象上,可以设置字体、字号、颜色等参数。 3. 添加干扰元素:为了防止机器识别验证码,需要在图片上添加干扰元素,例如噪点、曲线等。 4. 输出图片:使用 Java 的 ImageIO 类将 BufferedImage 对象输出为图片文件或者直接输出到响应流中。 以下是一个简单的示例代码: ```java public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应类型为图片 response.setContentType("image/jpeg"); // 生成随机字符串 String code = generateCode(); // 将随机字符串绘制到图片上 BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 100, 30); g.setColor(Color.BLACK); g.setFont(new Font("Arial", Font.BOLD, 20)); g.drawString(code, 10, 20); // 添加干扰元素 Random random = new Random(); for (int i = 0; i < 20; i++) { int x = random.nextInt(100); int y = random.nextInt(30); g.drawOval(x, y, 1, 1); } // 输出图片 ImageIO.write(image, "JPEG", response.getOutputStream()); } private String generateCode() { StringBuilder builder = new StringBuilder(); Random random = new Random(); for (int i = 0; i < 6; i++) { int code = random.nextInt(10) + 48; // ASCII码值范围:48-57 builder.append((char) code); } return builder.toString(); } ``` 在 Servlet 中调用 doGet 方法即可生成图片验证码,可以在 HTML 表单中添加一个图片标签,设置 src 属性为 Servlet 的 URL,然后用户在提交表单时同时提交验证码,进行验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值