AJAX+jsp无刷新验证码实例
1、我们在做验证码的时候往往由于要反作弊,验证有时故意加入多的干扰因素,这时验证码显示不很清楚,用户经常输入错误。这样不但要重新刷新页面,导致用户没有看清楚验证码而重填而不是修改,而且如果没有用session保存下用户输入的其它数据的话(如姓名),用户刚刚输入的内容也不存在了,这样给用户造成不好的体验。
2、本例在原有验证方式基础之上增加一段js,通过xmlhttp来获取返回值,以此来验证是否有效,这样即使用户浏览器不支持js,也不会影响他的正常使用了。
3、为了防止作弊,当用户连接3次输入错误时则重载一下图片,这样也利于用户因为图片上的验证码辨认不清而使其终无法输入正确。
4、本例还特别适合检验用户名是否有效,只要从后台做个sql查询,返回一个值或是xml 即可。(这种例子太多,就在此不赘述了)。
5、本例的优点在于非常方便用户输入,而且减少对服务器端的请求,可以说既改善用户体验而且略会节省带宽成本,但相应地要在页面上增加一段JavaScript代码,在目前网速越来越快人们要求便捷舒适的今天,似乎我们更应注意提供给用户良好的使用感受。
代码如下:
1、img.jsp,输入主页面
2、num.jsp,反馈xmlhttp请求的页面
3、random.jsp,生成验证码图片的页面
4、net.js,封装好的xmlhttp对象,可以很方便的调用
jsp验证码两个实例
2009-09-01 19:00:34| 分类:java | 标签:|字号大中小订阅
第一种方案:
用JSP来生成彩色验证码
读者可能经常在一些论坛发表帖子或用户登录时要求用户输入验证码,并在验证码输入框后生成了一张验证码的图片,只有验证码输入正确后才能继续下一步操作,那么使用验证码有什么用处,在JSP中又如何实现呢?举个例子,在论坛中发表帖子时,一般的Web程序都是以提交表单形式来提交帖子的内容,接收数据后插入到数据库的表中;如果有人不怀好意,利用一些自动提交表单的工具来不断的提交表单,则会导致数据库中的数据迅速膨胀,很快就会导致数据库的空间被用光如果使用了验证码,由于验证码生成的是图片,程序很难识别出来,而且图片中还可加入干扰,即便是使用了OCR(景像识别)技术也很难识别出来,当验证码没有通过时,数据就不会被提交到数据库中
为登录生成彩色验证码
本例将在登录页面生成彩色验证码,这样用户在登录时就要输入用户名密码和验证码,只有三个同时通过
才会通过检验
这里,把生成验证码图片的程序封装为一个JavaBean,这个JavaBean的源代码如下:
package securityCode.pic;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
/*生成验证码图片
*/
public class MakeCertPic {
//验证码图片中可以出现的字符集,可以根据需要修改
private char mapTable[]={
'a','b','c','d','e','f',
'g','h','i','j','k','l',
'm','n','o','p','q','r',
's','t','u','v','w','x',
'y','z','0','1','2','3',
'4','5','6','7','8','9'
/* 功能:生成彩色验证码图片
参数wedth为生成图片的宽度,参数height为生成图片的高度,参数os为页面的输出流
*/
public String getCertPic(int width,int height,OutputStream os){
if(width<=0)
width=60;
if(height<=0)
height=20;
BufferedImage image= new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取图形上下文
Graphics g = image.getGraphics();
//设定背景颜色
g.setColor(new Color(0xDCDCDC));
g.fillRect(0,0,width,height);
//画边框
g.setColor(Color.black);
g.drawRect(0,0,width-1,height-1);
//随机产生的验证码
String strEnsure = "";
//4代表4为验证码,如果要产生更多位的验证码,则加大数值
for(int i = 0;i<4;++i){
strEnsure += mapTable[(int) (mapTable.length*Math.random())];
}
//将认证码显示到图像中,如果要生成更多位的验证码,增加drawString语句
g.setColor(Color.black);
g.setFont(new Font("Atlantic Inline",Font.PLAIN,18));
String str = strEnsure.substring(0,1);
g.drawString(str,8,17);
str = strEnsure.substring(1,2);
g.drawString(str, 20, 15);
str = strEnsure.substring(2,3);
g.drawString(str, 35, 18);
str = strEnsure.substring(3,4);
g.drawString(str, 45, 15);
//随机产生15个干扰点
Random rand = new Random();
for(int i=0; i<10; i++){
int x = rand.nextInt(width);
int y = rand.nextInt(height);
g.drawOval(x,y,1,1);
}
//释放图形上下文
g.dispose();
//输出图形到页面
ImageIO.write(image, "JPEG", os);
}catch (IOException e){
return "";
}
return strEnsure;
}
}
在getCertPic()方法中,首先创建了一个内存图像的实例对象,再得到此内存图像的图形上下文对象,接着再用这个上下文对象画背景边框接下来,随机生成4个在mapTable[]数组中的字符,组成字符串作为验证字符串,并输出在内存中,为了造成一定的干扰,随机画了10个干扰点,如果要加大干扰效果,可再多画
一些点
makeCertPic.jsp页面用于调用生成验证码图片的JavaBean,并在客户端显示,源代码如下:
<%@page contentType="image/jpeg" %><%@page language="java"
pageEncoding="utf-8"%> class="securityCode.pic.MakeCertPic"/><% String str = image.getCertPic(0,0,response.getOutputStream()); //将验证码存入session中 session.setAttribute("certCode",str); %> 这里把生成的验证码作为session变量写入,因此在接收登录页面输入的数据页面中,可用用户输入的验证码和这个session变量作比较,如果相同则表示验证通过,注意:一定要将%><%中的空格与回车全部去掉,要不然就会抛出getOutputStream() has already been called for this response异常 下边是登录页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> "https://www.doczj.com/doc/fd5075752.html,/TR/html4/loose.dtd">
function changeimg()
{
var myimg = document.getElementById("code");
now = new Date();
myimg.src="makeCertPic.jsp?code="+now.getTime();
}
用户名:
密 码:
验证码:
登录页面的运行结果如图18-11所示
验证码的输入是否正确可用如下语句验证:
String certCode=request.getParameter("certCode");
if(certCode.equals((String)session.getAttribute("certCode")))
out.print("验证码输入正确");
else
out.print("验证码输入错误");
第二种方案:
不用java类,全部用jsp写:
生成有4个随机数字和杂乱背景的图片,数字和背景颜色会改变,服务器端刷新(用history.go(-1)
也会变)
------------产生验证码图片的文件-----image.jsp-------------------------------------------
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*"
%>
<%@page pageEncoding="utf-8" %>
<%!
Color getRandColor(int fc,int bc){//给定范围获得随机颜色
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
%>
<%
//设置页面不缓存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
// 在内存中创建图象
int width=60, height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
//生成随机类
Random random = new Random();
// 设定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
//设定字体
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
//画边框
//g.setColor(new Color());
//g.drawRect(0,0,width-1,height-1);
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160,200));
for (int i=0;i<155;i++)
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x,y,x+xl,y+yl);
}
// 取随机产生的认证码(4位数字)
String sRand="";
for (int i=0;i<4;i++){
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
// 将认证码显示到图象中
g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//调
用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand,13*i+6,16);
}
// 将认证码存入SESSION
session.setAttribute("rand",sRand);
// 图象生效
g.dispose();
// 输出图象到页面
ImageIO.write(image, "JPEG", response.getOutputStream());
//下边两行是防止抛出getOutputStream() has already been called for this response异常的
out.clear();
out = pageContext.pushBody();
%>
---------------使用验证码图片的文件---------a.jsp------------------------------------
<%@ page contentType="text/html;charset=gb2312" %>
function changeimg()
{
var myimg = document.getElementById("code");
now = new Date();
myimg.src="makeCertPic.jsp?code="+now.getTime();
}