基于Servlet的验证码设计与实现

2018-11-15 01:33丁乙诗任云宏兰全祥
电脑知识与技术 2018年20期
关键词:干扰

丁乙诗 任云宏 兰全祥

摘要:验证码能够有效防止暴力破解、恶意灌水以及自动注册等,在WEB开发中具有至关重要的作用。首先对Servlet技术进行了简介,其次按照MVC架构模式对验证码的实现进行了分析,并阐述了验证码的实现步骤。最后,重点讲解了字符型验证码、中文验证码的设计原理及实现,同时介绍了为验证码添加干扰的方法。

关键词:Servlet;验证码;干扰;网站开发

中圖分类号:TP311.1 文献标识码:A 文章编号:1009-3044(2018)20-0025-02

Design and Implementation of Verification Code Based on Servlet

DING Yi-shi, REN Yun-hong, LAN Quan-xiang

(Panzhihua University, Panzhihua 617000, China)

Abstract: Verification code can effectively prevent brute force, spam and automatic registration. It plays an important role in WEB development. First, the Servlet technology is introduced. Secondly, the implementation of the verification code is analyzed Based on the MVC architecture mode, and the development steps of the verification code are described. Finally, the design principles and implementation of character and Chinese verification code are explained. This paper introduces the method of adding interference to the verification code.

Key words: servlet; verification code; interference; website development

1 背景

验证码又称为全自动区分计算机和人类的图灵测试(CAPTCHA,Completely Automated Public Turing test to tell Computers and Humans Apart),是一种区分用户是计算机还是人的公共全自动程序。它能有效防止某些恶意用户对某些特定用户或网站使用暴力破解等方式进行的不断的非法攻击,如自动注册、重复登录、刷票、论坛灌水等[1]。

验证码经过长期的发展,已经演变出了图片验证码、知识型问题验证码、行为型验证码、短信验证码、信息校验验证码,其中图片验证码是设计难度较低且应用最广泛的验证码之一[2]。图片验证码一般是由数字、英文以及中文组成,其位数一般为四位,位数越多,识别难度越大。

2 Servlet技术简介

Servlet是用Java编写的服务器端程序,主要功能在于交互式地访问和修改数据,并生成动态Web内容。

2.1 Servlet API

Servle实现了javax.servlet.Servletr接口,在Servlet接口中定义了三个方法,分别为init方法、service方法和destroy方法。

init()方法主要用于servlet容器创建servlet实例时进行Servlet初始化;service()方法用于处理客户端向服务器发出的请求,并对服务器的响应进行设置;destroy()方法用于在服务器停止时销毁Servlet。

2.2 Servelet的创建与配置

Servlet的创建实质上是创建一个继承了HttpServlet类的Java类,创建时应遵循命名规范(类名首字母大写)。

在Tomcat6.0之后,Servlet可以通过注解进行配置,具体配置为:@WebServlet(urlPatterns = {" urlPatterns "}),其中urlPatterns属性用于指定servlet的映射路径。

3 验证码设计

一般情况下,WEB开发都是按照MVC三层结构进行设计的,因此笔者从视图层、控制层、模型层分别对验证码的设计和实现进行阐述。

3.1 视图层

视图层主要用于显示验证码和用户输入验证码。在视图层需编写验证码图片代码:

title="点击刷新"

onclick="checkCode()" id="imge"/>

其中,ImgServlet为验证码的请求地址(控制层Servlet映射URL),当验证码无法识别时,用户可以点击验证码进行刷新,关键代码如下:

function checkCode(){

imge.src = "ImgServlet?nocache="

+new Date().getTime();

}

3.2 控制层

控制层主要由Servlet技术来实现,其主要用于接收视图层发送的请求(生成验证码),并调用模型层进行数据处理,再将结果(验证码图片)响应到视图层。在控制层实现中需注意禁止图片缓存并设置响应类型为图片。

禁止缓存是为了确保验证码及时刷新,保证验证码的有效性,关键代码如下:

Response.setHeader("Pragma","No-cache");

Response.setHeader("Cache-Control","No-cache");

Response.setDateHeader("Expires","0");

由于请求的数据是图片,因此需设置响应内容类型,关键代码如下:

Response.setContentType("image/jpeg");

除上述步骤外,控制层还需调用模型层生成验证码的方法,并将正确的验证码字符保存到session中,然后将生成的验证码图片响应到视图层。

3.3 模型层

模型层是实现验证码生成的java类。在这个类中主要通过随机数生成器(Random)产生正确的验证码字符,并使用GDI+(Graphics Device Interface plus,图形设备接口)技术来实现验证码的绘制[3]。

4 验证码设计与实现

4.1 字符验证码

字符验证码一般包含英文和数字,这种验证码实现简单、快速,但是识别难度低,容易被破解。字符验证码的设计和实现步骤如下:

1)初始化验证码字符串

String ctmp = "";

2)将待选字符存入数组

char [] char = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

3)从数组中随机选取n个字符

Random random = new Random();

for(int i = 0; i

int index=random.nextInt(char.length);

ctmp += char[index];}

4)将验证码绘制在图片上

graphics.drawString(code, x, y);

其中,graphics为验证码图片的画笔,code为正确验证码字符,x和y是绘制验证码的坐标。生成的验证码示例图如图1所示。

4.2 中文验证碼

由于字符型验证码识别难度较低,为了提高验证码的识别难度,在生成验证码时可以选择绘制中文字符。GB2312编码规定汉字由四个区位码组成,其中汉字编码范围为B0A1—F7FE,且从区位D7开始以后的汉字都是和很难见到的繁杂汉字(不适用于生成验证码),因此验证码所选范围为B0A1—D7FE[4]。又因为区位码表每区的第一个位置和最后一个位置为空,因此??A0和??FF不可取(如B1区的B1A0和B1FF不可取)。中文验证码生成流程图如图3所示。

1)初始化验证码字符串

String ctmp="";

2)初始化区位码数组

String []rbase = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","d","e","f"};

3)随机生成n个汉字

Random random = new Random();

for(int i=0; i

//生成第一位区码

int r1 = random.nextInt(3)+11;

String str_r1 = rbase[r1];

//根据第一位区码生成第二位区码

int r2;

if(r1==13){ r2 = random.nextInt(7);

}else{r2 = random.nextInt(16);}

String str_r2 = rbase[r2];

//生成第一位位码

int r3 = random.nextInt(6)+10;

String str_r3 = rbase[r3];

//根据第一位位码生成第二位位码

int r4;

if(r3==10){r4 = random.nextInt(15)+1;

}else if(r3==15){r4 = random.nextInt(15);

}else{r4 = random.nextInt(16);}

String str_r4 = rbase[r4];

//将四位区位码转为字节数组

byte[] bytes = new byte[2];

String str_r12 = str_r1+str_r2;

int tempLow = Integer.parseInt(str_r12,16);

bytes[0] = (byte)tempLow;

String str_r34 = str_r3+str_r4;

int tempHigh = Integer.parseInt(str_r34,16);

bytes[1] = (byte)tempHigh;

//根据字节数组生成汉字

code = new String(bytes);

ctmp+=code;

}

4)将验证码绘制在图片上

graphics.drawString(ctmp, x, y);

生成的验证码示例图片如图2所示:

4.3 添加干扰

为了增加识别难度,可以在验证码图片上添加干扰,如随机线、随机颜色、随机缩放拉伸、背景干扰、旋转随机角度等[5]。

1)添加随机干扰线

int n = random.nextInt(15)+20;

//随机生成20-35条干扰线;

for (int i = 0; i

//随机生成干扰线的起点和终点

int xstart = (int)(Math.random() * width); int ystart = (int)(Math.random() * height);

int xend = (int)(Math.random() * width); int yend = (int)(Math.random() * height);

g.drawLine(xstart, ystart, xend, yend); }

2)縮放和随机旋转

Graphics2D g2d = (Graphics2D) g;

AffineTransform trans=new AffineTransform();

trans.rotate(random.nextInt(45) * Math.PI / 180, anchorx, anchory);

float scaleSize = random.nextFloat() +0.8f;

if (scaleSize > 1f) scaleSize = 1f;

trans.scale(scaleSize, scaleSize);

g2d.setTransform(trans);

添加随机干扰线之后的验证码实例如图3所示:

5 结束语

验证码能够有效防止自动注册、暴力破解(重复登录尝试)、恶意灌水等行为。该文介绍了基于Servlet的验证码生成技术,讲解了最广泛使用的基于数字与英文字母的验证码以及破解难度大和安全性高的中文验证码。为了提高验证码的识别难度,还介绍了添加干扰的方法。验证码作为网络服务的一种标准安全保障已被广泛使用,其实现技术也是开发人员必须要掌握的技能之一。

参考文献:

[1] 龚莎. 网页验证码技术综述[J]. 信息与电脑: 理论版, 2014(2): 143-144.

[2] 张立新. 多种类型验证码的研究与分析[J]. 福建电脑, 2016, 32(10): 76, 125.

[3] 李军, 连俊光. 基于GDI+的Web端页面验证码绘制[J]. 电脑知识与技术, 2018, 14(3): 72-73.

[4] 李凯胜. 中文验证码识别技术研究[D]. 西安: 西安电子科技大学, 2014.

[5] 蔺佳哲, 王茜, 谢楠. 基于WEB开发技术的新型验证码的设计研究[J]. 石家庄学院学报,2016, 18(3): 38-41.

猜你喜欢
干扰
“TD-LTE与其他系统间干扰问题”的实践测试
蜂窝网络终端直通通信功率控制研究
大颗粒尿素水分测定干扰原因分析与处理
乙肝治疗别被干扰素“干扰”
科学处置调频广播信号对民航通信干扰实例