验证码的出现有效地防止了服务器被恶意利用的问题的出现。So,现在的应用基本都会用到验证码,而对于我们来说,需要掌握的不仅仅是验证码的作用,所以今天就做了一个简单的验证码。虽然目前市面上有很多第三方验证码接口或者框架,例如ValidateCode.jar等,还是自己动手做一个玩玩。(哈哈哈,废话一啪啦)。
为了玩这个,还回去看了一下j2se的内容(java画图就没怎么玩...)
先准备一个生成验证码图的jsp,CheckCodeImg.jsp,步骤就在注释中,基本是j2se的知识,就不赘述了。
不过还是说说代码第一行吧,contentType需要写为:image/jpeg。表示整个文件类型为jpeg图片。
最后一行代码:开始时:out=pageContext.getOut()得到的是jsp内置out对象,后来pushBody得到的是一个新的ContextBody对象,他们是二个对象
ContextBody是JspWriter的子类;即:jsp内置out对象是父,pushbody得到的是子,
所以这里的out.close()其实不是close掉jsp的内置out对象,而是ContextBody的实例对象;
在jsp执行完后会释放所有内置对象,这里我们将该对象释放!
基本执行的顺序是:
1.生成验证码,并将验证码真实值放入session域中
2.显示验证码,将用户输入验证码值传回后端等待比对结果
3.后端接前端用户输入验证码值并和session中真实的验证码值比对,返回处理结果
4.前端接受返回结果,根据返回的值来显示给用户。
<%@ page contentType="image/jpeg;charset=UTF-8" language="java" %>
<%@ page import="java.awt.*" %>
<%@ page import="java.util.Random" %>
<%@ page import="java.awt.image.BufferedImage" %>
<%@ page import="javax.imageio.ImageIO" %>
<%!
//生成随机颜色
public Color getColor()
{
Random ran=new Random();
int R=ran.nextInt(255);
int G=ran.nextInt(255);
int B=ran.nextInt(255);
return new Color(R,G,B);
}
//生成随4位机数字验证码
public String codeGenerate()
{
int code=(int)(Math.random()*9000+1000);
return String.valueOf(code);
}
%>
<%
//禁止缓存,防止验证码过期
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setHeader("Expires","0");
//实例化一个image长度和宽度分别是80 30
BufferedImage image=new BufferedImage(80,30,BufferedImage.TYPE_INT_RGB);
//取画笔,准备画图
Graphics pen=image.getGraphics();
//填充该矩形image
pen.fillRect(0, 0, 80, 30);
//设置文字样式
pen.setFont(new Font("seif",Font.BOLD,20));
//设置画笔颜色
pen.setColor(Color.BLACK);
//获取随机数验证码值
String checkCode = codeGenerate() ;
//处理该验证码值的每一位数字
StringBuffer sb = new StringBuffer() ;
for(int i=0;i<checkCode.length();i++){
sb.append(checkCode.charAt(i)+" " ) ;
}
//绘制验证码
pen.drawString( sb.toString(), 15,20 );
//绘制干扰线条
for(int i=0;i<20;i++)
{
Random ran = new Random() ;
//产生随机起始位置
int xBegin = ran.nextInt(80) ;//55
int yBegin = ran.nextInt(30) ;
//干扰线条末端位置
int xEnd = ran.nextInt(xBegin +15 ) ;
int yEnd = ran.nextInt(yBegin + 15) ;
//设置随机线条颜色
pen.setColor( getColor());
pen.drawLine(xBegin,yBegin,xEnd,yEnd);
}
//将验证码真实值 保存在session中,供使用时比较真实性
session.setAttribute("CKECKCODE" ,checkCode );
//真实的产生图片
ImageIO.write(image,"jpeg", response.getOutputStream()) ;
//关闭
out.clear();
out = pageContext.pushBody() ;
%>
然后,再写另一个jsp,来测试这个验证码,就叫test.jsp
这里用了jq,在我的服务器端有一个文件夹imgs里面放了两个图片,分别是 x 和 ✔,当输入框失去焦点,会自动使用ajax方式请求后台并判断验证码是否正确,若正确就显示✔,否则显示 x。此外点击验证码可以刷新一张新的验证码。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<script type="text/javascript" src="jquery-3.3.1.js" >
</script>
<script type="text/javascript" >
//实现点击一下验证码就刷新一张
function reloadCheckImg()
{
$("img").attr("src", "CheckCodeImg.jsp?"+(new Date().getTime())); //<img src="...">
}
$(document).ready(function()
{
$("#checkcodeId").blur(function()
{
var $checkcode = $("#checkcodeId").val();
//校验 :文本框中输入的值 发送到服务端。
//服务端: 获取文本框输入的值 ,和真实验证码图片中的值对比 ,并返回验证结果
$.post(
"ServiceCheckCode",//服务端地址
"checkcode="+$checkcode ,
function(result)
{
var resultHtml = $("<img src='"+result+"' height='15' width='15px' />") ;
$("#tip").html(resultHtml);
}
);
});
});
</script>
<title>验证码</title>
</head>
<body>
验证码:
<input type="text" name="checkcode" id="checkcodeId" size="4" />
<!-- 验证码-->
<a href="javascript:reloadCheckImg();"> <img src="CheckCodeImg.jsp"/></a>
<span id="tip"> </span>
</body>
</html>
。最后,服务端代码,ServiceCheckCode.java;简单地从session中拿到验证码的值,然后和前端test.jsp传来的验证码值进行比对,若比对成功,将提示正确的图片地址返回去,让前端显示(就是那个 ✔)。否则默认返回表示错误的图片地址。
package com.charles.service;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ServiceCheckCode")
public class ServiceCheckCode extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String resultTip = "imgs/wrong.jpg";
//获取用户输入验证码
String checkcodeClient = request.getParameter("checkcode");
//真实的验证码值
String checkcodeServer = (String) request.getSession().getAttribute("CKECKCODE");
if(checkcodeServer.equals(checkcodeClient)){
resultTip = "imgs/right.jpg";
}
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();//输出流
writer.write(resultTip);
writer.flush();
writer.close();
}
}
最后附上两张测试图
正确 错误