700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 在JSP中动态生成随机验证码 登录时后台校验验证码 以及如何避免同一个验证码被重复

在JSP中动态生成随机验证码 登录时后台校验验证码 以及如何避免同一个验证码被重复

时间:2022-06-12 02:46:28

相关推荐

在JSP中动态生成随机验证码 登录时后台校验验证码 以及如何避免同一个验证码被重复

只需几步就可以生成动态随机的验证码,最终效果如下图:

一 前台显示页面login.jsp

其中验证码显示的是一张图片,链接指向的是生成验证码的servlet,同时点击图片后触发changeImg()这个js函数,使其动态生成一个新的验证码,这个函数中的参数t=Math.random()并不会参与验证码的生成,它的作用仅仅只是表示每次提交的并不是同一个请求,需要单独处理,完整的login.jsp代码如下:

<%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%><%Stringpath=request.getContextPath();StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""/TR/html4/loose.dtd"><html><head><metahttp-equiv="Content-Type"content="text/html;charset=UTF-8"><basehref="<%=basePath%>"><%@includefile="head.txt"%><scripttype="text/javascript">//刷新验证码functionchangeImg(){document.getElementById("validateCodeImg").src="helpDrawValidateCode?t="+Math.random();}</script></head><body><fontsize=3><center><formaction="helpLogin"name=""method="post"><table><tr><th>请您登陆:</th></tr><tr><tdalign=left>会员名称:</td><td><inputtype=textname="id"></td></tr><tr><tdalign=left>输入密码:</td><td><inputtype=passwordname="password"></td></tr></table><br>验证码:<inputtype="text"name="validateCode"style="width:50px"><imgalt="看不清?换一张"src="helpDrawValidateCode"id="validateCodeImg"οnclick="changeImg()"><br><inputtype="submit"value="提交"></form></center></font></body></html>

二 修改web.xml

新增一个节点,代码如下:

<!--验证码绘制--><servlet><servlet-name>drawValidateCode</servlet-name><servlet-class>com.zifangsky.OnlineFriend.servlet.member.HandleDrawValidateCode</servlet-class></servlet><servlet-mapping><servlet-name>drawValidateCode</servlet-name><url-pattern>/helpDrawValidateCode</url-pattern></servlet-mapping>

三 后台的servlet文件HandleDrawValidateCode.java

这个文件主要负责处理前台请求,并返回生成的验证码图片,同时将图片上的随机字符存入session中,以供登录时进行验证,HandleDrawValidateCode.java完整代码如下:

packagecom.zifangsky.OnlineFriend.servlet.member;importjava.awt.Color;importjava.awt.Font;importjava.awt.Graphics;importjava.awt.Graphics2D;importjava.awt.p_w_picpath.BufferedImage;importjava.io.IOException;importjava.util.Random;importjavax.p_w_picpathio.ImageIO;importjavax.servlet.ServletConfig;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;/***生成随机图片用做验证码**/publicclassHandleDrawValidateCodeextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;privatestaticfinalintWIDTH=120;//图片宽度privatestaticfinalintHEIGHT=30;//图片高度publicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);}publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");HttpSessionsession=request.getSession(true);//创建一张图片BufferedImagebufferedImage=newBufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);//得到图片Graphicsgraphics=bufferedImage.getGraphics();//设置图片背景色setBackGround(graphics);//设置图片边框setBordor(graphics);//在图片上画干扰线,用了4种颜色,共20条线条drawRandomLine(graphics,Color.GREEN);drawRandomLine(graphics,newColor(246,255,145));drawRandomLine(graphics,newColor(225,174,252));drawRandomLine(graphics,newColor(120,202,254));//在图片上写随机字符,并记录生成的序列StringrandomText=drawRandomText((Graphics2D)graphics);//将生成的字符存入session中session.setAttribute("checkcode",randomText);//设置响应头通知浏览器以图片的形式打开response.setContentType("p_w_picpath/jpeg");//设置响应头控制浏览器不要缓存response.setDateHeader("expries",-1);response.setHeader("Cache-Control","no-cache");response.setHeader("Pragma","no-cache");//将图片写给浏览器ImageIO.write(bufferedImage,"jpg",response.getOutputStream());}/***设置图片背景色**/privatevoidsetBackGround(Graphicsgraphics){graphics.setColor(Color.WHITE);graphics.fillRect(0,0,WIDTH,HEIGHT);}/***设置图片边框**/privatevoidsetBordor(Graphicsgraphics){graphics.setColor(Color.BLUE);graphics.drawRect(1,1,WIDTH-2,HEIGHT-2);}/***在图片上画干扰线**/privatevoiddrawRandomLine(Graphicsgraphics,Colorcolor){graphics.setColor(color);//设置线条个数并画线for(inti=0;i<5;i++){intx1=newRandom().nextInt(WIDTH);intx2=newRandom().nextInt(WIDTH);inty1=newRandom().nextInt(HEIGHT);inty2=newRandom().nextInt(HEIGHT);graphics.drawLine(x1,y1,x2,y2);}}/***在图片上写随机字符,数字和字母的组合*@paramlength字符串的长度**@return返回生成的字符串序列**/privateStringdrawRandomText(Graphics2Dgraphics){graphics.setColor(Color.RED);graphics.setFont(newFont("宋体",Font.BOLD,20));//数字和字母的组合StringbaseNumLetter="123456789ABCDEFGHJKLMNPQRSTUVWXYZ";StringBuffersBuffer=newStringBuffer();intx=5;//旋转原点的x坐标Stringch="";Randomrandom=newRandom();for(inti=0;i<4;i++){//设置字体旋转角度intdegree=random.nextInt()%30;//角度小于30度intdot=random.nextInt(baseNumLetter.length());ch=baseNumLetter.charAt(dot)+"";sBuffer.append(ch);//正向旋转graphics.rotate(degree*Math.PI/180,x,20);graphics.drawString(ch,x,20);//反向旋转graphics.rotate(-degree*Math.PI/180,x,20);x+=30;}returnsBuffer.toString();}publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doPost(request,response);}}

注:

在这里,干扰线的颜色和数目都可以自己设定,颜色可以使用随机色,同时显示的每个文字也可以使用随机的颜色,可以增加验证码识别难度,当然在这里我把比较容易混淆的0和O以及I都给去掉了。如果选用经过编码的中文字符的话,也是可以生成中文验证码的

四 login.jsp页面提交表单后,后台的servlet文件HandleLogin.java校验验证码,并进行登录验证

经过上面的三个步骤后,login.jsp应该是可以正确显示验证码了,同时点击验证码图片后会生成一个新的验证码,login.jsp提交表单后HandleLogin.java文件验证验证码时主要是:将输入的验证码中的小写字母转换成大写,再和验证码生成时保存在session中的字符串比较,如果相同,则表示输入正确,同时移除session中设置的值,防止重复提交,爆破密码,HandleLogin.java相关代码如下:

packagecom.zifangsky.OnlineFriend.servlet.member;importjava.io.IOException;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjavax.servlet.RequestDispatcher;importjavax.servlet.ServletConfig;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;importcom.zifangsky.OnlineFriend.model.member.Login;importcom.zifangsky.OnlineFriend.util.DbConn;importcom.zifangsky.OnlineFriend.util.StringUtil;publicclassHandleLoginextendsHttpServlet{privateStringbackNews="";//登录状态返回信息publicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);}publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");HttpSessionsession=request.getSession(true);//获取验证码StringvalidateCode=StringUtil.xssEncode(request.getParameter("validateCode").trim());Objectcheckcode=session.getAttribute("checkcode");//将输入的验证码中的小写字母转换成大写,再和验证码生成时保存在session中的字符串比较if(checkcode!=null&&checkcode.equals(StringUtil.convertToCapitalString(validateCode))){session.removeAttribute("checkcode");continueDoPost(request,response);}else{response.sendRedirect("login.jsp");return;}}privatevoidcontinueDoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{//这里的登录后续操作省略}publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doPost(request,response);}}

注1:上面用到的StringUtil是我写的一个字符串相关的方法类,其中用到的方法convertToCapitalString()目的是将一个字符串中的小写字母转换为大写字母,代码如下:

/***将一个字符串中的小写字母转换为大写字母***/publicstaticStringconvertToCapitalString(Stringsrc){char[]array=src.toCharArray();inttemp=0;for(inti=0;i<array.length;i++){temp=(int)array[i];if(temp<=122&&temp>=97){//array[i]为小写字母array[i]=(char)(temp-32);}}returnString.valueOf(array);}

注2:其中方法xssEncode()是将输入的字符串进行编码,以此避免产生XSS跨站脚本***,用的是commons-lang-2.4.jar里的StringEscapeUtils,代码如下(PS:当然在这里没有什么必要,可以省略):

/***字符串XSS过滤,JavaScript过滤,Sql过滤**@paramstr传入的字符串**@return转义后的字符串**/publicstaticStringxssEncode(Stringstr){Strings=StringEscapeUtils.escapeHtml(str);//s=StringEscapeUtils.escapeJavaScript(s);//s=StringEscapeUtils.escapeSql(s);returns;}

在JSP中动态生成随机验证码 登录时后台校验验证码 以及如何避免同一个验证码被重复提交爆破密码...

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。