一、知识点的名称
验证码
二、知识点的简介
验证码(captcha):大家都知道为了防止我们的网站被有些人和黑客恶意攻击,比如我们网站的注册页面,如果我们在用户注册时候不加上一个验证框的话,别人就可以写一个脚本对你的网站进行恶意的注册,比如每分钟对你的网站进行N次的注册,那么你的网站就会被攻击而崩溃,当时我们增加了验证码之后,别人再写脚本的时候就必须先识别你的验证码,而要识别验证码中的内容,却不是那么的容易,这样就能够有效的防止我们的网站被恶意的注册攻击.
三、知识点业务场景
1、案例:新浪微博登录
四、功能实现步骤
功能描述:
效果如下:
实现步骤及核心代码
1、制作index.jsp页面
验证码包括两部分:
1)、输入框
2)、显示验证码的图片
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>$http://localhost:8080/$</title>
</head>
<body>
<table>
<tr>
<td colspan="100">
验证码测试
</td>
</tr>
<tr>
<td colspan="100">
<form action="<%=request.getContextPath()%>/servlet/LoginServlet">
验证码:<input type="text" name="checkcode"/>
<img alt="验证码" id="imagecode" src="<%=request.getContextPath()%>/servlet/ImageServlet"/>
<a href="javascript:reloadCode();">看不清楚</a><br>
<input type="submit" value="提交"/>
</form>
</td>
</tr>
</table>
</body>
</html>
2、制作验证码,创建一个名为Image Servlet.java的Servlet类
生成图片所用到的类
1)、BufferedImage图像数据缓冲区
2)、Graphics绘制图片
3)、Color获取颜色
4)、Random生成随机数
5)、ImageIO输出图片生成图片的实现类
生成图片所用到的类
1)、定义BufferedImage对象
2)、获得Graphics对象
3)、通过Random产生随机验证码信息
4)、使用Graphics绘制图片
5)、记录验证码信息到Session对象中
6)、使用ImageIO输出图片
/**
* Copyright (C), 2015-2018,
* FileName: ImageServlet
* Author: arr_int
* Date: 2018/11/8 9:54
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package www.wd.com.controller;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author WangDuo
* @create 2018/11/8
* @since 1.0.0 */
public class ImageServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.定义BufferedImage对象,参数(宽度,高度,图片类型)
BufferedImage bi = new BufferedImage(68, 22, BufferedImage.TYPE_INT_RGB);
//2.获得Graphics对象
Graphics g = bi.getGraphics();
//3.设置颜色
Color c = new Color(200,150,255);
//4.把颜色给g对象
g.setColor(c);
//5.画框
g.fillRect(0, 0, 68, 22);
//6.指定验证码内容
char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
//7.创建random随机对象获取验证码
Random r = new Random();
int len = ch.length; //获取ch长度
int index; //创建一个随机索引变量
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对象中
sb.append(ch[index]);
}
//将验证码保存到Session对象中,方便之后进行验证
request.getSession().setAttribute("piccode", sb.toString());
ImageIO.write(bi, "JPG", response.getOutputStream());
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 将ImageServlet配置到web.xml文件中 -->
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>www.wd.com.controller.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/servlet/ImageServlet</url-pattern>
</servlet-mapping>
<!-- 将ImageServlet配置到web.xml文件中 -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>www.wd.com.controller.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
</web-app>
就此以可以启动服务器进行测试了
4.实现"看不清楚"刷新验证码功能
给页面添加一个script脚本方法
<script type="text/javascript" src="/WEB-INF/js/jquery-1.8.3.js"></script>
<script type="text/javascript">
function reloadCode() {
var time = new Date().getTime();
document.getElementById("imagecode").src="<%=request.getContextPath()%>/servlet/ImageServlet?d="+time;
}
</script>
解析:脚本中reloadCode()方法中time的作用:防止刷新时出现缓冲器生效导致刷新不成功的情况.
修改href接下来可以在尝试点击看不清楚验证码是否能够刷新.
5.验证码的效验功能
首先我们让表单提交到Servlet验证地址,填写提交地址
创建相对应的Servlet类------LoginServlet.java
/**
* Copyright (C), 2015-2018,
* FileName: LoginServlet
* Author: arr_int
* Date: 2018/11/8 9:55
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package www.wd.com.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author WangDuo
* @create 2018/11/8
* @since 1.0.0 */
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//首先获取原来的验证码信息
String piccode = (String) request.getSession().getAttribute("piccode");
//获取用户填写的验证码
String checkcode = request.getParameter("checkcode");
//设置返回结果的字符集
response.setContentType("text/html;charset=gbk");
//创建输出流对象
PrintWriter out = response.getWriter();
//判断验证码是否正确
//使用equalsIgnoreCase()方法比较字符串可以忽略大小写
if (checkcode.equalsIgnoreCase(piccode) ) {
out.print("验证码输入正确!");
}else {
out.print("验证码输入错误!");
}
//刷新并关闭流
out.flush();
out.close();
}
}
五、完整的项目
大家可以试一试看看实现效果.
六、总结
验证码虽然用的非常广泛,表面上看起来也并不会增加太多操作,但如非必要,千万不可滥用,验证码的具体表现形式非常多,
具体使用哪种验证码,需要综合考虑开发成本、用户体验等多个因素.