验证码简介
对于验证码,相信每个人都不会陌生,当我们在一个网站进行注册登录时,发布帖子时,经
常需要输入验证码进行验证,但其实这对用户体验来说很不友好,我们需要多输入一次和我们貌
似没有太大关系的数据,那为什么大多数网站都有网页验证码呢?
那么没有验证码会带来哪些问题?
1. 对特定用户不断登录破解密码
2. 对某个网站重复创建账户
3. 对某个网站提交垃圾数据
4. 对某网站刷票
所以使用验证码还是很有必要的!
用Servlet实现验证码步骤
首先是制作页面
验证码包含两个部分:输入框和图片
输入框很简单<input type="text" name="verifyCode" />
图片不太一样<img alt="验证码" id="checkcode" src="<%=request.getContextPath() %>/ImageServlet"
这里src并不是指向一个固定的图片,而是指向我们用于生成图片的ImageServlet类,request.getContextPath()
得到当前项目路径。
生成图片
生成图片所需要的类
1.BufferedImage类(存放图片)
2.Graphics类(绘制图片,字体)
3.Color类(设置颜色)
4.Random(生成图片上的随机字符)
5.ImageIO类(输出图片)生成图片的实现类
1.定义BufferedImage对象
2.获得Graphics对象
3.获得Random产生随机验证码信息
4.使用Graphics绘制图片
5.记录验证码到session中
6.使用ImageIO输出图片校验验证码是否正确
1.获取页面验证码
2.获取session中保存的验证码
3.比较验证码
4.返回校验结果
实现流程
代码实现
生成验证码
首先是图片生成类ImageServlet
import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; 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("/ImageServlet") public class ImageServlet extends HttpServlet{ @Override //生成图片并设置颜色大小 BufferedImage bi = new BufferedImage(68, 22, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics(); Color c = new Color(200, 150, 255); g.setColor(c); g.fillRect(0, 0, 68, 22); //生成一个字符数组,从中随机抽取字符 String str = "ABCDEFGHI0123456789"; char[] ch = str.toCharArray(); Random r = new Random(); int len = ch.length,index; //随机抽取4位字符画入图片并将字符存入StringBuffer中 StringBuffer sb = new StringBuffer(); for(int i =0 ;i<4;i++) { index = r.nextInt(len); g.setColor(new Color(r.nextInt(88), r.nextInt(188), r.nextInt(255))); g.drawString(ch[index]+"", (i*15)+3, 18); sb.append(ch[index]); } //将StringBuffer中的字符存入Session中以备后续校验,并输出图片 request.getSession().setAttribute("piccode", sb.toString()); ImageIO.write(bi, "JPG", response.getOutputStream()); } }
此时运行服务可以看到页面显示出验证码
通常验证码后面有“看不清楚”,然而此时点击并没有反应,因为我们并没有设置这个标签的链接,这里就用到javascript,设置<a href="javascript:reloadCode();">看不清楚</a>
a标签指向一个javascript的reloadCode()
函数,点击链接就会刷新出不同的图片,所以我们只是重新加载一次 ImageServlet类 生成图片,代码如下:
<script type="text/javascript">
function reloadCode(){
var time = new Date().getTime();
//获取元素名为imagecode的元素并设置其src路径指向ImageServlet类
document.getElementById("imagecode").src="<%=request.getContextPath() %>/ImageServlet?d="+time;
}
</script>
这里为什么要加一个time变量呢?这是因为我们如果不加time变量那么图片的路径是没有变化的,浏览器觉得加载同一张图没有必要,不知道是新的请求还是旧的请求,所以图片并不会变化,而加入time之后每次加载的都不是同一张图片,从而进行刷新图片。
校验验证码
用户输入图片内容之后接下来就是校验验证码是否正确,我们将页面上的表单提交给LoginServlet类进行处理,处理的流程就是:
1.将Session中存的内容取出来 2.将用户输入的内容提取出来 3.进行比较,并输出比较结果
LoginServlet类
public class LoginServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("GBK");
//取出两者内容传给piccode,checkcode。
String piccode = (String) request.getSession().getAttribute("piccode");
String checkcode = request.getParameter("checkcode");
//将用户输入的字符转换成大写
checkcode = checkcode.toUpperCase();
PrintWriter out = response.getWriter();
//进行比较并返回结果
if(checkcode.equals(piccode)) {
out.println("验证码输入正确!");
}else {
out.println("验证码输入错误!");
}
out.flush();
out.close();
}
}
到这里我们的验证码就完成了,赶紧打开页面去试试吧!