在web开发领域里面,验证码是一个比较常见的功能,而归根到底,验证码其实就是一组随机数,或者是一个随机算术

一、基本知识

1、为什么需要验证码?

验证码,很多时候出现在注册页面或者登陆界面,在这些页面中有可能会出现恶意注册和暴力破解,这时候验证码可以有效防范这些攻击。所以,总的来说,验证码很多时候是为了防止不法分子对网站进行恶意的注册和攻击,是一种有效的拦截手段。

2、验证码的工作原理

  首先,我们要明确一点就是,验证码实际是在服务器端产生的,因为如果在前端参数的话并不能有效拦截,因此很多时候,在拦截时我们都需要在服务器端进行相关操作,防止黑客绕过前端验证直接非法访问。

  验证码的工作原理其实方几个步骤:首先,服务端随机产生几个随机数或者随机算式,然后通过session对象将数据传输到客户端,客户端输入验证码,通过r表单将数据提交到服务器,服务器提取数据之后和产生的随机数字或者算式的结果对比,以此进行验证。

  当然,很多时候,简单的验证码很容易被图像识别软件破解,所以现在很多时候更流行短信验证等方式,但是,一下讨论的均是简单的数字图片验证。

二、验证码的实现过程

1、首先,验证码其实就是在服务端产生一张带有验证码数字或者算式的图片,所以,在这个过程要用到gui知识,具体请先看一下代码

//1、验证码界面
//验证码的宽和高
int width = 70;
int height = 30;
/*
*图像缓冲对象(注意:在多次对某个对象操作时,为了提高效率,很多时候选择用缓冲对象来进行操作,
因为缓冲类的对象很多时候是可以即时改变对象的数据的)
*/
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//创建图像操作对象,用于操作验证码图片对象
Graphics2D g = bufferedImage.createGraphics();
//创建字体对象方便操作图像字体的属性
Font font = new Font("Times New Roman",Font.PLAIN,18);
g.setFont(font);
//设置相关颜色等等
g.setColor(Color.BLACK);
g.drawRect(0,0,width-1,height-1);
g.setColor(Color.GRAY);

  以上创建了一个基本的验证码图片,注意很多时候如果要反复对象对某个对象进行修改操作时(如某个字符串,需要反复进行拼接操作时,为提高性能,一般选择用缓冲类的对象进行操作之后再转换为相关对象)。以上是产生验证码的gui主要代码,具体的步骤不啰嗦了,请参考代码吧。

2、创建好相关的验证码图片界面之后,下一步就是产生随机数了,请先看以下代码:

//2、产生随机数
//定义生成随机数的对象
Random random = new Random();
//产生干扰线
for(int i=0;i<40;i++){
//设置40条干扰线
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = random.nextInt(10);
int y2 = random.nextInt(10);
//将随机线条描绘到验证码对象中
g.drawLine(x1,y1,x1+x2,y1+y2);
}
//产生随机数
//定义随机数的个数
int length = 4
//定义 变量存储随机数字变量
BufferedString str_random = new BufferedString();//定义成缓冲字符类型是为了提高效率
for(int i=0;i<length;i++){
int num_random = random.nextInt(10);
String str_num = String.valueOf(num_random);
g.drawString(str_num);
str_random.append(str_num);
}

  以上主要通过Random随机数产生对象来产生随机数字,其中注意要在反复第String类型操作的时候,将其定义成BufferedString进行操作比较高效。具体的操作并没有涉及什么新技术,请查看代码。

3、完成产生随机数的步骤之后,剩下的就是将产生的随机数发送出去了。请看代码

//3、发送验证码图片数据
bufferedImg.flush();//刷新与图像缓冲有关的数据
g.dispose();//释放与Graphice2D有关的对象的资源
String randomCode = str_random.toString();
session.setAttribute("randomCode",randomCode.toString());//通过session传递随机码给其他页面用于验证身份
ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(bufferedImg,"jpeg",outputStream); outputStream.close(); out.clear();
out=pageContext.pushBody();

  以上的发送验证码也是比较简单,只是通过网络流进行发送操作,其中,注意Graphics2D的资源释放和IO流的关闭就好了。其中,将验证码通过session发送给其他页面使用。

三、总结

以上实现了简单的数字验证码功能,其中涉及到的技术主要是javaGUI、IO操作和servlet技术的session技术。类似的,实现算式的验证码也是类似的步骤,具体的就不多说,下面的代码是实现了简单的算式验证码的代码参考:

int width = 70,height = 22;
if(request.getParameter("width")!=null){
try{
width=Integer.parseInt(request.getParameter("width"));
}catch(NumberFormatException e) { }
}
BufferedImage bufferedImg = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImg.createGraphics(); g.setColor(Color.WHITE);
g.fillRect(0,0,width,height); Font font = new Font("Times New Roman",Font.PLAIN,18);
g.setFont(font); g.setColor(Color.BLACK);
g.drawRect(0,0,width-1,height-1);
g.setColor(Color.GRAY); Random random = new Random();//设置随机种子 for(int i=0;i<40;i++){
//设置40条干扰线
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = random.nextInt(10);
int y2 = random.nextInt(10);
g.drawLine(x1,y1,x1+x2,y1+y2);
} int length = 4;//设置默认生成四个长度的验证码
if(request.getParameter("length")!=null){
try{
length = Integer.parseInt(request.getParameter("length"));
}catch(NumberFormatException e){
out.println("<script>alert('无法加载验证码,请重新操作!')</script");
e.printStackTrace();
}
}
//定义变量存储运算结果
int result = 0;
//定义一个int用于存储某个数字后面的运算符,1代表+,2代表-,初始化为0
int int_sign = 0;
for(int i = 0;i<length;i++){//获取随机数字字符串
int num_random = random.nextInt(10);
//根据符号标记标量int_sign进行相应的运算
if(int_sign==2){
result = result - num_random;
}else{
result = result + num_random;
}
String strRand = String.valueOf(num_random);
g.setColor(Color.RED);
g.drawString(strRand,13 * i + 6, 16);
//随机获取运算符号
if(i<length-1){
int sign_random = random.nextInt(2);
if(sign_random<1){
g.setColor(Color.GREEN);
g.drawString("+",13 * i + 12, 16);
int_sign = 1;
}else{
g.setColor(Color.BLUE);
g.drawString("-",13 * i + 12, 16);
int_sign = 2;
}
}else{
g.drawString("=?",13 * i + 12, 16);
} }
bufferedImg.flush();
g.dispose(); session.setAttribute("randomCode",result); response.setContentType("image/jpeg");
response.setHeader("Pragam","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires",0); ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(bufferedImg,"jpeg",outputStream); outputStream.close(); out.clear();
out=pageContext.pushBody();

  好了,验证码的总结就到此结束,有什么不足的地方请各位大神指正!

jsp实现验证码的更多相关文章

  1. 使用jsp生成验证码

    在开发中验证码是比较常用到有效防止这种问题对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试的方式. 此演示程序包括三个文件: 1.index.jsp:登录页面 2.image.jsp:生成 ...

  2. Jsp制作验证码

    验证码 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart&qu ...

  3. jsp页面验证码(完整实例)

    项目结构如下,MyEclipse中新建一个Web Project,取名servlet 1.src下new一个servlet类 package com.servlet; import java.awt. ...

  4. jsp实现验证码登陆

    login.jsp: <%@ page language="java" import="java.util.*,com.cn.servlet.*" pag ...

  5. jsp 生成验证码代码

    调用方法:在jsp页面用图像标签便可以直接调用如下是标签代码<img border=0 src="image.jsp">,只需要把该代码发在验证码要显示的区域就可以了) ...

  6. Jsp+servlet 验证码案例

    昨晚在csdn看到一位前辈写一个ajax+servlet+jsp验证.顿时心血来潮,在阅读前辈的代码下我亲手体验一下,做了一个验证码生成工具类.以供大家做个參考. 1:加入VeriyCodeUtils ...

  7. JSP页面验证码实现

    首先在JSP页面加上生成图片的链接 <img type="image" src="auth/authCode" id="codeImage&qu ...

  8. jsp的验证码实现

    package com.xunfang.demo; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; imp ...

  9. JSP生成验证码

    <%@ page language="java" import="java.util.*" pageEncoding="gbk"%&g ...

随机推荐

  1. Photoshop 使用曲线

    曲线表示的是图像的明度, 通过信息办的 HSB 信息可以看到调整曲线时整个图像明度的变化 曲线的左下角表示图片的暗部, 右下角表示图片的高光部 而曲线本身的纵坐标则表示这个部分的明度, 例如将曲线的左 ...

  2. Android--多线程之Handler(转)

    前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的 ...

  3. 2748: [HAOI2012]音量调节

    Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改 ...

  4. php pdo预处理语句与存储过程

    很多更成熟的数据库都支持预处理语句的概念.什么是预处理语句?可以把它看作是想要运行的 SQL 的一种编译过的模板,它可以使用变量参数进行定制.预处理语句可以带来两大好处: 1.查询仅需解析(或预处理) ...

  5. 【洛谷P2296】寻找道路

    反正图两边bfs #include<iostream> #include<cstdio> #include<queue> using namespace std; ...

  6. JS-定时器管理实例函数封装

    /** * Created by 12461 on 2016/11/6. */window.onload = function () { var oBtn1 = document.getElement ...

  7. vsftpd的主动模式与被动模式

    好不容易配置好了vsftpd服务,在CentOS本机测试没有问题,但是在我的Windows机器上使用FlashFXP连接的时候却出问题了: 我虽然知道FTP存在两种模式:PORT(主动)模式.PASV ...

  8. Please set registry key HKLM\Microsoft\.NET Framework\InstallRoot to point to the .NET Framework

    安装.NET程序时会提示“Please set registry key HKLM\Microsoft\.NET Framework\InstallRoot to point to the .NET ...

  9. mysql 怎么查询出,分组后的总条数。。。也就是有多少组数。。。。怎么写

    SELECT COUNT(*) AS 多少组数FROM( SELECT id FROM 表 GROUP BY id) subQuery;Mysql,有一个表含有以下字段,uid 发帖人id,title ...

  10. 解决 yum安装时报错 Error: Protected multilib versions: 报错

    系统中缺少一个lib库 libz.so.1文件,使用yum安装会自动找到相关的rpm包,如下命令 # yum -y install libz.so.1 Resolving Dependencies-- ...