JAVAWEB项目如何实现验证码

验证码基础

一.什么是验证码及它的作用

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

 

二.图文验证码的原理

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

 

三.验证码所需的技术

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

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

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

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

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

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

 

验证码模块实例

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

[java] view plaincopy
  1. package com.servlet;  
  2.   
  3. import java.awt.*;  
  4. import java.awt.geom.*;  
  5. import java.awt.image.*;  
  6. import java.io.*;  
  7. import java.util.*;  
  8.   
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. import javax.servlet.http.HttpSession;  
  14. import javax.imageio.ImageIO;  
  15.   
  16. public class PictureCheckCode extends HttpServlet {  
  17.   
  18.     private static final long serialVersionUID = 1L;  
  19.   
  20.     public PictureCheckCode() {  
  21.         super();  
  22.     }  
  23.   
  24.     public void destroy() {  
  25.         super.destroy();   
  26.     }  
  27.   
  28.     public void init() throws ServletException {  
  29.         super.init();  
  30.     }  
  31.     /*该方法主要作用是获得随机生成的颜色*/   
  32.     public Color getRandColor(int s,int e){  
  33.         Random random=new Random ();  
  34.         if(s>255) s=255;  
  35.         if(e>255) e=255;  
  36.         int r,g,b;  
  37.         r=s+random.nextInt(e-s);    //随机生成RGB颜色中的r值  
  38.         g=s+random.nextInt(e-s);    //随机生成RGB颜色中的g值  
  39.         b=s+random.nextInt(e-s);    //随机生成RGB颜色中的b值  
  40.         return new Color(r,g,b);  
  41.     }  
  42.   
  43.     @Override  
  44.     public void service(HttpServletRequest request, HttpServletResponse response)  
  45.             throws ServletException, IOException {  
  46.         //设置不缓存图片  
  47.         response.setHeader("Pragma", "No-cache");  
  48.         response.setHeader("Cache-Control", "No-cache");  
  49.         response.setDateHeader("Expires", 0);  
  50.         //指定生成的响应图片,一定不能缺少这句话,否则错误.  
  51.         response.setContentType("image/jpeg");  
  52.         int width=86,height=22;     //指定生成验证码的宽度和高度  
  53.         BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //创建BufferedImage对象,其作用相当于一图片  
  54.         Graphics g=image.getGraphics();     //创建Graphics对象,其作用相当于画笔  
  55.         Graphics2D g2d=(Graphics2D)g;       //创建Grapchics2D对象  
  56.         Random random=new Random();  
  57.         Font mfont=new Font("楷体",Font.BOLD,16); //定义字体样式  
  58.         g.setColor(getRandColor(200,250));  
  59.         g.fillRect(0, 0, width, height);    //绘制背景  
  60.         g.setFont(mfont);                   //设置字体  
  61.         g.setColor(getRandColor(180,200));  
  62.           
  63.         //绘制100条颜色和位置全部为随机产生的线条,该线条为2f  
  64.         for(int i=0;i<100;i++){  
  65.             int x=random.nextInt(width-1);  
  66.             int y=random.nextInt(height-1);  
  67.             int x1=random.nextInt(6)+1;  
  68.             int y1=random.nextInt(12)+1;  
  69.             BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL); //定制线条样式  
  70.             Line2D line=new Line2D.Double(x,y,x+x1,y+y1);  
  71.             g2d.setStroke(bs);  
  72.             g2d.draw(line);     //绘制直线  
  73.         }  
  74.         //输出由英文,数字,和中文随机组成的验证文字,具体的组合方式根据生成随机数确定。  
  75.         String sRand="";  
  76.         String ctmp="";  
  77.         int itmp=0;  
  78.         //制定输出的验证码为四位  
  79.         for(int i=0;i<4;i++){  
  80.             switch(random.nextInt(3)){  
  81.                 case 1:     //生成A-Z的字母  
  82.                      itmp=random.nextInt(26)+65;  
  83.                      ctmp=String.valueOf((char)itmp);  
  84.                      break;  
  85.                 case 2:     //生成汉字  
  86.                      String[] rBase={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};   
  87.                      //生成第一位区码  
  88.                      int r1=random.nextInt(3)+11;  
  89.                      String str_r1=rBase[r1];  
  90.                      //生成第二位区码  
  91.                      int r2;  
  92.                      if(r1==13){  
  93.                          r2=random.nextInt(7);     
  94.                      }else{  
  95.                          r2=random.nextInt(16);  
  96.                      }  
  97.                      String str_r2=rBase[r2];  
  98.                      //生成第一位位码  
  99.                      int r3=random.nextInt(6)+10;  
  100.                      String str_r3=rBase[r3];  
  101.                      //生成第二位位码  
  102.                      int r4;  
  103.                      if(r3==10){  
  104.                          r4=random.nextInt(15)+1;  
  105.                      }else if(r3==15){  
  106.                          r4=random.nextInt(15);  
  107.                      }else{  
  108.                          r4=random.nextInt(16);  
  109.                      }  
  110.                      String str_r4=rBase[r4];  
  111.                      //将生成的机内码转换为汉字  
  112.                      byte[] bytes=new byte[2];  
  113.                      //将生成的区码保存到字节数组的第一个元素中  
  114.                      String str_12=str_r1+str_r2;  
  115.                      int tempLow=Integer.parseInt(str_12, 16);  
  116.                      bytes[0]=(byte) tempLow;  
  117.                      //将生成的位码保存到字节数组的第二个元素中  
  118.                      String str_34=str_r3+str_r4;  
  119.                      int tempHigh=Integer.parseInt(str_34, 16);  
  120.                      bytes[1]=(byte)tempHigh;  
  121.                      ctmp=new String(bytes);  
  122.                      break;  
  123.                 default:  
  124.                      itmp=random.nextInt(10)+48;  
  125.                      ctmp=String.valueOf((char)itmp);  
  126.                      break;  
  127.             }  
  128.             sRand+=ctmp;  
  129.             Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));  
  130.             g.setColor(color);  
  131.             //将生成的随机数进行随机缩放并旋转制定角度 PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示  
  132.             /*将文字旋转制定角度*/  
  133.             Graphics2D g2d_word=(Graphics2D)g;  
  134.             AffineTransform trans=new AffineTransform();  
  135.             trans.rotate((45)*3.14/180,15*i+8,7);  
  136.             /*缩放文字*/  
  137.             float scaleSize=random.nextFloat()+0.8f;  
  138.             if(scaleSize>1f) scaleSize=1f;  
  139.             trans.scale(scaleSize, scaleSize);  
  140.             g2d_word.setTransform(trans);  
  141.             g.drawString(ctmp, 15*i+18, 14);  
  142.         }  
  143.         HttpSession session=request.getSession(true);  
  144.         session.setAttribute("randCheckCode", sRand);  
  145.         g.dispose();    //释放g所占用的系统资源  
  146.         ImageIO.write(image,"JPEG",response.getOutputStream()); //输出图片  
  147.     }  
  148. }  

 

 2.配置Servlet

    在web.xml中的配置如下:

[java] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5"   
  3.     xmlns="http://java.sun.com/xml/ns/javaee"   
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  7.   <servlet>  
  8.     <description>输出验证码</description>  
  9.     <display-name>This is the display name of my J2EE component</display-name>  
  10.     <servlet-name>PictureCheckCode</servlet-name>  
  11.     <servlet-class><SPAN style="COLOR: #ff0000">com.servlet.PictureCheckCode</SPAN></servlet-class>  
  12.   </servlet>  
  13.   
  14.   <servlet-mapping>  
  15.     <servlet-name>PictureCheckCode</servlet-name>  
  16.     <url-pattern>/<SPAN style="COLOR: #ff0000">PictureCheckCode</SPAN></url-pattern>  
  17.   </servlet-mapping>  
  18.   <welcome-file-list>  
  19.     <welcome-file>index.jsp</welcome-file>  
  20.   </welcome-file-list>  
  21. </web-app>  


3.测试验证码

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

    1.index.jsp:显示界面

[java] view plaincopy
  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中保存的验证码是否相同

[java] view plaincopy
  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>  


 

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

转载于:https://www.cnblogs.com/jpwpp/p/6255291.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在线判题系统(oj)效果分析图_在线代码编写平台开发分享

计算机专业的大学生应该都了解acm比赛&#xff0c;这种通过使用oj(online judge)系统在线编程刷题&#xff0c;实时反馈学习排名的方式能很大程度激发学生的学习热情。oj学习排名界面oj个人学习记录界面只是oj平台一般都只适用后端语言&#xff0c;如java&#xff0c;c#, c,C&a…

BZOJ1298:[SCOI2009]骰子的学问

Description Input 第一行为两个整数n, m。第二行有n个整数&#xff0c;为a1&#xff0c;a2, …, an。 Output 包含n行&#xff0c;每行m个1~nm的正整数&#xff0c;各不相同&#xff0c;以空格分开。如果有多解&#xff0c;输出任意一组解&#xff1b;如果无解&#xff0c;输出…

mysql交叉连接后生成的记录总数_4.mysql数据库创建,表创建模等模板脚本,mysql_SQL99标准的连接查询(内连接,外连接,满外连接,交叉连接)_MySQL...

--用root用户登录系统&#xff0c;执行脚本--创建数据库create database mydb61 character set utf8 ;--选择数据库use mydb61;--增加 dbuser1用户--创建用户‘dbuser61’密码为‘dbuser61’拥有操作数据库mydb61的所有权限GRANT ALL ON mydb61.* TO dbuser61 IDENTIFIED BY &q…

IIS网站或系统验证码不显示问题——使用了托管的处理程序,但是未安装或未完整安装 ASP.NET...

在IIS上发布了一个系统&#xff0c;但是登陆页面的验证码图片一直出不来&#xff0c;尝试了各种办法&#xff0c;权限、路径、继承父类路径等都不管用&#xff0c;进入Login.html,对着无验证码图片的图标&#xff0c;右键复制图片的网址&#xff0c;粘贴到地址栏&#xff0c;出…

mysql索引有字符集_07. 类型、字符集、引擎和索引

字符集是什么&#xff1f;为了更好的识别中文、日文、英文、希腊语。对于常用的符号进行了编码&#xff0c;这个编码就是字符集。字符集确定了文字的存储方式。字符集相当于是计算机中人类的语言。举个例子&#xff1a;我说的是英文&#xff0c;所以我存储的时候要用英文文字来…

oracle--第一天PLSQL--bai

第一天&#xff1a; -- 创建book表 create table book ( bid number primary key, bname varchar2(20) not null, price number(10,2) not null ) -- 插入数据 insert into book(bid,bname,price)values(20,西游记,170.5); insert into book(bid,bname,price)values(12,红楼梦,…

mysql性能优化的8个方法_关键的十个MySQL性能优化技巧

与所有的关系型数据库一样&#xff0c;Mysql仿佛是一头让人难以琢磨的怪兽。它会随时停摆&#xff0c;让应用限于停滞&#xff0c;或者让你的业务处于危险之中。事实上&#xff0c;许多最常见的错误都隐藏在MySQL性能问题的背后。为了确保你的MySQL服务器能够一直处于全速运行的…

修改自己的centos输入法

当自己的centos连上网时&#xff0c;就可以修改自己的输入法了 http://jingyan.baidu.com/album/da1091fb3e7f8a027849d681.html?picindex2 转载于:https://www.cnblogs.com/xiaoyoucai/p/6262054.html

new float查询长度 c++_C/C++经典面试题

面试题 1&#xff1a;变量的声明和定义有什么区别 为变量分配地址和存储空间的称为定义&#xff0c;不分配地址的称为声明。一个变量可以在多个地方声明&#xff0c; 但是只在一个地方定义。加入 extern 修饰的是变量的声明&#xff0c;说明此变量将在文件以外或在文件后面部分…

git相关资料

https://github.com/xirong/my-git 转载于:https://www.cnblogs.com/zhao1949/p/6265503.html

mysql动态变量查询_MySQL将变量传递给动态查询

对不起&#xff0c;如果这是一个基本问题&#xff01; 直至现在我已经创造了PHP的MySQL查询和跨变量传递SQL调用中是这样的&#xff1a;MySQL将变量传递给动态查询$myparam $_GET["id_tbl"];mysql_select_db($database_camerich, $camerich);$query_rs_table sprin…

java8--IO(java疯狂讲义3复习笔记)

产生文件 File file new File("abc.txt");if(!file.exists()){System.out.println(file.exists());file.createNewFile();}System.out.println(file.getAbsolutePath()); 关于临时文件 1).放在指定目录,此时已项目为默认目录 File file File.createTempFile("…

python网络平台_python学习(九) 网络编程学习--简易网站服务器

python 网络编程和其他语言都是一样的&#xff0c;服务器这块步骤为&#xff1a;1. 创建套接字2. 绑定地址3. 监听该描述符的所有请求4. 有新的请求到了调用accept处理请求Python Web服务器网关接口(Python Web Server Gateway Interface&#xff0c;简称“WSGI”)&#xff0c;…

LeetCode 451. Sort Characters By Frequency

Mediocre solution is O(nlgn) by using max-heap - but, remember bucket sort? it is O(n)转载于:https://www.cnblogs.com/tonix/p/6269000.html

rabbit和mysql事务_分布式事务原理及SpringBoot整合RabbitMQ实现可靠事件,TCC事务模型及接口幂等性...

分布式事务我们知道在单数据库系统中&#xff0c;实现数据的一致性&#xff0c;通过数据库的事务来处理比较简单。在微服务或分布式系统中&#xff0c;各个独立的服务都会有自己的数据库&#xff0c;而不是在同一个数据库中&#xff0c;所以当一组事务(如商品交易中&#xff0c…

rhel Linux 网络配置

--网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 1)DHCPDEVICEeth0BOOTPROTOdhcpONBOOTyes2)静态IP DEVICEeth0 BOOTPROTOnone IPADDR192.168.0.22 NETMASK255.255.255.0GATEWAY192.168.0.254DNS11…

如何下载php-5.5.38.tar.gz_搭建PHP服务器php-5.3.28.tar.gz

构建PHP运行环境PHP所用的软件 &#xff1a;php-5.3.28.tar.gz优化模块 &#xff1a;ZendGuardLoader-php-5.3-linux-glibc23-x86_64.tar.gz(两者之间版本一样)准备工作&#xff1a;卸载RPM安装的PHP[rootlocalhost php]# rpm -e php php-cli php-ldap php-common php-mysql --…

004-全局应用程序类Global.asax

服务器对象&#xff1a;Request、Response、Server、Session、Application、Cookie //功能1&#xff1a;为服务器对象注册Start、End处理 protected void Application_Start(object sender, EventArgs e){} protected void Application_End(object sender, EventArgs e){} 管道…

mysql创建表的时候日期给个默认值_mysql 创建表时 日期字段默认值为当前时间...

mysql 创建表时 日期字段默认值为当前时间mysql version 5.1在mysql创建表的时候经常会遇到创建日期字段需要设置当前时间为默认值的时候&#xff0c;就如sqlserver2000一样&#xff0c;把默认值设为getdate()即可&#xff0c;我在网上查了N久都没有查到使用有效的方法&#xf…

Android onKeyDown、onKeyUp、dispatchKeyEvent的区别

1. onKeyDown、onKeyUp、dispatchKeyEvent的区别和使用场景 区别&#xff1a;   1.1 onKeyDown、onKeyUp是按键事件的回调接口&#xff08;冒泡式调用&#xff09;&#xff0c;dispatchKeyEvent是按键分发&#xff08;隧道式分发&#xff09; 1.2 onKeyDown接口的回调只…