WEB站点有时会碰到客户机恶意攻击,其中一种很常见的攻击手段就是身份欺骗.它通过在客户端脚本写入一些代码,然后利用客户机在网站、论坛反复登录来嗅探一些用户名和密码;或者创建一个HTML窗体,其窗体如果包含了注册窗体或发帖窗体等相同的字段,然后利用“Http-post”传输数据到服务器。服务器会执行相应的操作,提交垃圾数据等,严重浪费服务器系统资源。
而现在一般的判断访问者是否合法的方式,就是采用一种叫“字符校验”的技术,即WEB网站为客户提供一个包含随机字符串的图片,用户必须读取这些字符串,然后随登录窗体或者发帖窗体一起提交。因为人的话,可以很容易读出图片中的字符串,但如果是一段客户端攻击代码,通过一般手段很难识别验证码。
简单将就是将一串随机产生的数字或者符号,生成一幅图片,图片里加上一些干扰像素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证码,验证成功后才能使用某项功能。
验证码一般是防止有人利用机器人自动批量注册、对特定的注册用户用特定程序暴力破解方式进行不断的登录、灌水。因为验证码是一个混合了数字或符号的图片,加上一些干扰像素,人眼看起来都费劲,机器识别起来就更困难。
随机数字+随机大写字母+随机位置+随机长度
图片上的随机数字+随机大写字母,每次刷新字符位置还会变化
随机数字+随机大写字母+随机干扰像素+随机位置
内容随机
在Java中要生成验证码,主要涉及到绘图技术:
1)坐标体系
和计算机上的其他编程语言一样,在绘图的平面区域上我们想象有一个二维坐标,通过它就可以把绘图和写字位置标示清楚。在java中坐标原点(0,0)位于整个绘图平面的左上角,从原点出发向右为x轴,向下为y轴。所有的坐标都必须是整数,一个单位代表一个像素。所以要把一个图像或字放在一整个指定位置,只要指出它的x和y坐标就可以了。
2)字形设置
(1) 字体设置
public Font(String Fontname,int style,int size);
Fontname表示所要选择的字体名称,如”TimesRoman”、”Courier等;
Style为字体的表现形式,有正常字体(PLAIN),粗体(BOLD)等;
Size为字体的大小
(2) 显示字形
显示方法可以使用Graphics类中的下列方法
a) drawstring(Stringstr,int x,int y);
str:表示被显示的字符串;
X:表示X轴坐标
Y:表示Y轴坐标
b) drawChars(chardata[],int offset,int length,int x,int y)
c) drawBytes(bytedata[],int offset,int length,int x,int y)
d) setFont(Fontfont)
e) getFont();返回当前图形对象的字体
(3) 颜色设置
用Color类,在Java中Color类将颜色按照RGB格式进行封装。RGB格式中,红蓝绿三原色的取值范围都是0-255.若取0则表示不起任何作用,若取255表示起最大作用。RGB=”000000”表示黑色,RGB=”FFFFFF”表示白色。首先调用Color的构造函数,产生一个Color对象,再用Graphics类里的setColor()把它设置到Graphics对象上。
(4) 画线
DrawLine(int x1,int y1,int x2,inty2);
在(x1,y1)和(x2,y2)这两个坐标之间画出一条直线。
(5) 绘制普通矩形
Java提供了3种矩形的绘制方法
a) drawRect(intx,int y,int width,int height) 功能是画出一个矩形
b) fillRect(intx,int y,int width,int height) 使用当前图形对象的颜色填充参数指定的矩形
c) 绘制立体矩形
draw3DRect(int x,int y,int width,int height,Boolean raised)绘制一个突出的三维立体矩形,raised为true,则表示立体矩形为凸起形状,否则为凹下。
fill3DRect(int x,int y,int width,int height,Boolean raised)绘制一个三维立体矩形并使用当前图像对象的颜色对其进行填充。
(6) 绘制圆角矩形
drawRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight) 绘制一个圆角矩形,arcWidth为圆弧的横向直径,arcHeigh为圆弧的纵向直径。
fillRoundRect(intx,int y,int width,int height,int arcWidth,intarcHeight) 绘制圆角矩形并使用当前图像对象的颜色对其进行填充。
// 验证码工具类
public class ImageCodeUtil
{
public static final String RANDOMKEY ="RANDOMKEY";
private Random random =new Random();
private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 种子字符串
private int width = 80; // 图片宽
private int height = 26; // 图片高
private int linesize = 10; // 干扰线数量
private int stringNum = 4; //随机产生字符数量
/*
* 获得字体
*/
private Font getFont()
{
return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
}
/*
* 获得颜色
*/
private ColorgetRandomColor(intfc, intbc)
{
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc -fc - 16);
int g = fc + random.nextInt(bc -fc - 14);
int b = fc + random.nextInt(bc -fc - 18);
return new Color(r, g, b);
}
/*
* 生成随机图片
*/
public void getRandomCode(HttpServletRequest request,
HttpServletResponse response)
{
//设置响应类型
response.setContentType("image/jpeg");
//浏览器不缓存验证码图片
response.setHeader("Pragm","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expire", 0);
HttpSession session = request.getSession();
// BufferedImage类是具有缓冲区的Image类
BufferedImage image = new BufferedImage(width,height,
BufferedImage.TYPE_INT_BGR);
// 生成Image对象的Graphics对象,该对象可以在图像上进行各种绘制操作
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times Roman", Font.ROMAN_BASELINE, 18));
g.setColor(getRandomColor(110, 133));
// 绘制干扰线
for (inti = 0; i < linesize; i++)
drowLine(g);
// 绘制随机字符
String randomString = "";
for (inti = 1; i <=stringNum; i++)
randomString = drowString(g,randomString, i);
session.removeAttribute(RANDOMKEY);
session.setAttribute(RANDOMKEY,randomString);
// 验证图片绘制完成,释放此图形的上下文以及它使用的所有系统资源。
g.dispose();
try
{
// 将内存中的图片通过流输出到客户端
ImageIO.write(image,"JPEG", response.getOutputStream());
}
catch (IOExceptione)
{
e.printStackTrace();
}
}
/*
* 绘制字符串
*/
private StringdrowString(Graphicsg, String randomString,int i)
{
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101),random.nextInt(111),
random.nextInt(121)));
String rand = String.valueOf(getRandomString(random.nextInt(randString
.length())));
randomString += rand;
/*
* 将图形上下文的原点平移到当前坐标系中的点 (x, y)。修改此图形上下文,使其新的原点对应于此图形上下文原坐标系中的点 (x, y)。
* 在此图形上下文上执行的后续呈现操作所用的所有坐标均相对于这个新原点。
*/
// 通过改变原点坐标使绘制的字符产生错位效果
g.translate(random.nextInt(3),random.nextInt(3));
g.drawString(rand, 13 *i, 16);
returnrandomString;
}
/*
* 获取随机的字符
*/
private StringgetRandomString(intnum)
{
return String.valueOf(randString.charAt(num));
}
/*
* 绘制干扰线
*/
private void drowLine(Graphics g)
{
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = random.nextInt(13);
int y2 = random.nextInt(15);
g.drawLine(x1,y1, x2, y2);
}
}
// 使用方式
@Controller
public class IndexController
{
@RequestMapping(value="/imagecode",method=RequestMethod.GET)
public void imagecode(HttpServletRequest request,HttpServletResponseresponse)
{
ImageCodeUtil imageCodeUtil=new ImageCodeUtil();
imageCodeUtil.getRandomCode(request,response);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/sunshuolei/article/details/48139095